当前位置:首页>python>生成遍历顺序对比说明文档 python代码

生成遍历顺序对比说明文档 python代码

  • 2026-10-11 07:42:29
生成遍历顺序对比说明文档 python代码

# -*- coding: utf-8 -*-

"""

生成遍历顺序对比说明文档 (docx)

"""

importos

importmatplotlib

matplotlib.use('Agg')

matplotlib.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimSun', 'KaiTi']

matplotlib.rcParams['axes.unicode_minus'] =False

importmatplotlib.pyplotasplt

importmatplotlib.patchesasmpatches

frommatplotlib.patchesimportFancyBboxPatch

import numpy asnp

from docx import Document

from docx.shared import Inches, Pt, Cm, RGBColor

from docx.enum.text import WD_ALIGN_PARAGRAPH

from docx.enum.table import WD_TABLE_ALIGNMENT

# ========== 配置 ==========

ROWS, COLS=4, 5

OUT_DIR=r'C:\Users\yl\Desktop'

IMG_DIR=os.path.join(OUT_DIR, '_temp_imgs')

os.makedirs(IMG_DIR, exist_ok=True)

# ========== 画图工具函数 ==========

defdraw_grid_with_arrows(ax, order, title, subtitle, order_name, 

arrow_color='#E74C3C', cell_bg='#F0F3F4',

highlight_color='#FADBD8', text_color='#2C3E50'):

"""绘制带箭头和序号的网格图"""

ax.set_xlim(-0.1, COLS-0.05)

ax.set_ylim(-0.1, ROWS-0.05)

ax.set_aspect('equal')

ax.axis('off')

# 标题

ax.text(COLS/2, ROWS+0.5, title, fontsize=14, fontweight='bold',

ha='center', va='center', color=text_color,

bbox=dict(boxstyle='round,pad=0.3', facecolor='#EBF5FB', alpha=0.8))

ax.text(COLS/2, ROWS+0.15, subtitle, fontsize=10,

ha='center', va='center', color='#7F8C8D')

# 绘制单元格

forrinrange(ROWS):

forcinrange(COLS):

idx=order[r, c]

# 根据顺序深浅着色

alpha=0.3+0.7* (idx/ (ROWS*COLS-1))

color=plt.cm.RdYlGn_r(alpha)

rect=FancyBboxPatch((c, ROWS-1-r), 1, 1, 

boxstyle="square,pad=0",

facecolor=color, edgecolor='#BDC3C7',

linewidth=1.5)

ax.add_patch(rect)

# 序号文字

ax.text(c+0.5, ROWS-1-r+0.5, str(idx+1),

ha='center', va='center', fontsize=11, fontweight='bold',

color='#2C3E50')

# 绘制箭头连线

order_list= []

forrinrange(ROWS):

forcinrange(COLS):

order_list.append((c, ROWS-1-r))

foriinrange(len(order_list) -1):

x1, y1=order_list[i]

x2, y2=order_list[i+1]

ax.annotate('', xy=(x2+0.5, y2+0.5), xytext=(x1+0.5, y1+0.5),

arrowprops=dict(arrowstyle='->', color=arrow_color,

lw=1.5, alpha=0.6))

# 添加顺序名称标签

ax.text(0.05, -0.4, f'→ {order_name}', fontsize=9, fontweight='bold',

color=arrow_color, transform=ax.transData)

defdraw_comparison_grid(ax, order, title, order_name, arrow_color):

"""绘制对比图(两个网格并排中的单个)"""

ax.set_xlim(-0.1, COLS-0.05)

ax.set_ylim(-0.1, ROWS-0.05)

ax.set_aspect('equal')

ax.axis('off')

ax.text(COLS/2, ROWS+0.3, title, fontsize=11, fontweight='bold',

ha='center', va='center', color='#2C3E50')

forrinrange(ROWS):

forcinrange(COLS):

idx=order[r, c]

alpha=0.3+0.7* (idx/ (ROWS*COLS-1))

color=plt.cm.RdYlGn_r(alpha)

rect=FancyBboxPatch((c, ROWS-1-r), 1, 1,

boxstyle="square,pad=0",

facecolor=color, edgecolor='#BDC3C7',

linewidth=1)

ax.add_patch(rect)

ax.text(c+0.5, ROWS-1-r+0.5, str(idx+1),

ha='center', va='center', fontsize=9, fontweight='bold',

color='#2C3E50')

order_list= []

forrinrange(ROWS):

forcinrange(COLS):

order_list.append((c, ROWS-1-r))

foriinrange(len(order_list) -1):

x1, y1=order_list[i]

x2, y2=order_list[i+1]

ax.annotate('', xy=(x2+0.5, y2+0.5), xytext=(x1+0.5, y1+0.5),

arrowprops=dict(arrowstyle='->', color=arrow_color,

lw=1, alpha=0.5))

# ========== 生成图片 ==========

# 1. 从左到右,从上到下(行优先)

order_row=np.zeros((ROWS, COLS), dtype=int)

forrinrange(ROWS):

forcinrange(COLS):

order_row[r, c] =r*COLS+c

fig1, ax1=plt.subplots(1, 1, figsize=(8, 7), dpi=150)

draw_grid_with_arrows(ax1, order_row, 

'方式一:从左到右 → 从上到下',

'(行优先 / Row-Major Order)',

'行优先遍历')

fig1.savefig(os.path.join(IMG_DIR, 'row_major.png'), bbox_inches='tight', pad_inches=0.3)

plt.close(fig1)

# 2. 从上到下,从左到右(列优先)

order_col=np.zeros((ROWS, COLS), dtype=int)

forcinrange(COLS):

forrinrange(ROWS):

order_col[r, c] =c*ROWS+r

fig2, ax2=plt.subplots(1, 1, figsize=(8, 7), dpi=150)

draw_grid_with_arrows(ax2, order_col,

'方式二:从上到下 ↓ 从左到右',

'(列优先 / Column-Major Order)',

'列优先遍历',

arrow_color='#3498DB')

fig2.savefig(os.path.join(IMG_DIR, 'col_major.png'), bbox_inches='tight', pad_inches=0.3)

plt.close(fig2)

# 3. 对比图

fig3, axes=plt.subplots(1, 2, figsize=(14, 7), dpi=150)

draw_comparison_grid(axes[0], order_row,

'从左到右,从上到下\n(行优先)',

'行优先', '#E74C3C')

draw_comparison_grid(axes[1], order_col,

'从上到下,从左到右\n(列优先)',

'列优先', '#3498DB')

fig3.suptitle('两种遍历顺序对比', fontsize=16, fontweight='bold', y=1.02)

fig3.savefig(os.path.join(IMG_DIR, 'comparison.png'), bbox_inches='tight', pad_inches=0.3)

plt.close(fig3)

# ========== 生成 Word 文档 ==========

doc= Document()

# 页面设置

forsectionindoc.sections:

section.page_width = Cm(21)

section.page_height = Cm(29.7)

section.left_margin = Cm(2.5)

section.right_margin = Cm(2.5)

section.top_margin = Cm(2)

section.bottom_margin = Cm(2)

# 标题

title=doc.add_heading('二维网格遍历顺序对比说明', level=0)

title.alignment = WD_ALIGN_PARAGRAPH.CENTER

doc.add_paragraph('')  # 空行

# ===== 一、概述 =====

doc.add_heading('一、概述', level=1)

p=doc.add_paragraph()

p.add_run('在二维网格(矩阵、栅格、图像像素等)中遍历所有单元格时,有两种最基本的遍历顺序:')

t=doc.add_table(rows=2, cols=2)

t.style ='Light Grid Accent 1'

t.alignment = WD_TABLE_ALIGNMENT.CENTER

t.cell(0, 0).text ='方式'

t.cell(0, 1).text ='说明'

t.cell(1, 0).text ='从左到右,从上到下'

t.cell(1, 1).text ='先遍历完当前行的所有列,再换到下一行(行优先 / Row-Major)'

# 设置表格字体

forrowint.rows:

forcellinrow.cells:

forparagraphincell.paragraphs:

forruninparagraph.runs:

run.font.size = Pt(11)

doc.add_paragraph('')

# ===== 二、详细说明 =====

doc.add_heading('二、方式一:从左到右,从上到下(行优先)', level=1)

doc.add_paragraph('遍历规则:')

p=doc.add_paragraph('每一行内,从左向右依次访问每个单元格', style='List Bullet')

p=doc.add_paragraph('当前行访问完毕后,换到下一行,继续从左到右', style='List Bullet')

p=doc.add_paragraph('所有行从上到下依次处理', style='List Bullet')

doc.add_paragraph('访问顺序公式:')

p=doc.add_paragraph()

run=p.add_run('index = row × 列数 + col')

run.font.name ='Consolas'

run.font.size = Pt(11)

run.font.color.rgb = RGBColor(0x2C, 0x3E, 0x50)

doc.add_paragraph('')

doc.add_paragraph('图示:')

doc.add_picture(os.path.join(IMG_DIR, 'row_major.png'), width=Cm(16))

doc.add_paragraph('')

doc.add_heading('三、方式二:从上到下,从左到右(列优先)', level=1)

doc.add_paragraph('遍历规则:')

p=doc.add_paragraph('每一列内,从上向下依次访问每个单元格', style='List Bullet')

p=doc.add_paragraph('当前列访问完毕后,换到下一列,继续从上到下', style='List Bullet')

p=doc.add_paragraph('所有列从左到右依次处理', style='List Bullet')

doc.add_paragraph('访问顺序公式:')

p=doc.add_paragraph()

run=p.add_run('index = col × 行数 + row')

run.font.name ='Consolas'

run.font.size = Pt(11)

run.font.color.rgb = RGBColor(0x2C, 0x3E, 0x50)

doc.add_paragraph('')

doc.add_paragraph('图示:')

doc.add_picture(os.path.join(IMG_DIR, 'col_major.png'), width=Cm(16))

# ===== 四、对比 =====

doc.add_heading('四、对比总结', level=1)

doc.add_paragraph('')

doc.add_paragraph('两种遍历顺序的直观对比:')

doc.add_paragraph('')

doc.add_picture(os.path.join(IMG_DIR, 'comparison.png'), width=Cm(16))

doc.add_paragraph('')

# 对比表格

t2=doc.add_table(rows=6, cols=3)

t2.style ='Light Grid Accent 1'

t2.alignment = WD_TABLE_ALIGNMENT.CENTER

headers= ['对比项', '从左到右 → 从上到下(行优先)', '从上到下 ↓ 从左到右(列优先)']

data= [

    ['遍历方向', '行内水平移动为主', '列内垂直移动为主'],

    ['内存访问', '行内连续访问,缓存友好', '列内跳跃访问,缓存不友好'],

    ['适用场景', 'C/C++/Python 数组、图像处理', 'Fortran/MATLAB 数组、GIS 栅格'],

    ['循环嵌套', '外层 for row,内层 for col', '外层 for col,内层 for row'],

    ['别名', 'Row-Major Order', 'Column-Major Order'],

]

forj, hinenumerate(headers):

cell=t2.cell(0, j)

cell.text =h

forpincell.paragraphs:

forruninp.runs:

run.font.bold =True

run.font.size = Pt(10)

fori, row_datainenumerate(data):

forj, valinenumerate(row_data):

cell=t2.cell(i+1, j)

cell.text =val

forpincell.paragraphs:

forruninp.runs:

run.font.size = Pt(10)

doc.add_paragraph('')

# ===== 五、示例代码 =====

doc.add_heading('五、代码示例', level=1)

doc.add_heading('5.1 行优先(从左到右,从上到下)', level=2)

code1="""# C / Python 风格 — 行优先

for row in range(ROWS):        # 外层:行(从上到下)

    for col in range(COLS):    # 内层:列(从左到右)

        visit(grid[row][col])

# 访问顺序:(0,0)→(0,1)→(0,2)→...→(1,0)→(1,1)→..."""

p=doc.add_paragraph()

run=p.add_run(code1)

run.font.name ='Consolas'

run.font.size = Pt(9)

run.font.color.rgb = RGBColor(0x2C, 0x3E, 0x50)

doc.add_heading('5.2 列优先(从上到下,从左到右)', level=2)

code2="""# 列优先遍历

for col in range(COLS):        # 外层:列(从左到右)

    for row in range(ROWS):    # 内层:行(从上到下)

        visit(grid[row][col])

# 访问顺序:(0,0)→(1,0)→(2,0)→...→(0,1)→(1,1)→..."""

p=doc.add_paragraph()

run=p.add_run(code2)

run.font.name ='Consolas'

run.font.size = Pt(9)

run.font.color.rgb = RGBColor(0x2C, 0x3E, 0x50)

# ===== 六、注意事项 =====

doc.add_heading('六、注意事项', level=1)

notes= [

'行优先是 C、C++、Python(NumPy 默认)等语言的数组存储方式',

'列优先是 Fortran、MATLAB、R 等语言的数组存储方式',

'在 GIS 栅格数据处理中,两种遍历方式都常见,需注意数据格式要求的存储顺序',

'行优先遍历时,相邻访问的内存地址连续,CPU 缓存命中率更高,性能通常更好',

'选择哪种遍历方式取决于具体应用场景和数据存储格式',

]

fornoteinnotes:

doc.add_paragraph(note, style='List Bullet')

# 保存

out_path=os.path.join(OUT_DIR, '遍历顺序对比说明_新.docx')

doc.save(out_path)

print(f'Document saved: {out_path}')

# 清理临时图片

importshutil

shutil.rmtree(IMG_DIR)

print('Temp images cleaned up.')

最新文章

随机文章