843 / 学习讲义

信息技术 / 06

算法与线性结构:让步骤可执行

一次解决一个小问题。从具体例子开始,理解条件,再亲手算一遍。

06 / 算法与线性结构:让步骤可执行 · 小节 1

算法、复杂度与递归

读完这一节,你会

用输入输出、终止条件和不变式解释一个算法。

大纲要求的教学展开 · 技术讲解 · 本节来源与考点

前置知识:数组、指针与结构体怎样配合 让计算机按顺序做事 · 符号回看

从一个问题开始

找出一摞书中编号最大的书,为什么“多试几次”不算完整算法?

调用向下,结果向上

调用向下,结果向上。步骤文字在图下。fact(3)fact(2)fact(1)fact(0)
1 / 3

fact(3)等待3×fact(2)。

原创教学示意 · 手动播放,可随时暂停;折叠或离开小节时停止。

把这件事讲清楚

算法是解决一类问题的有限、明确、可执行步骤,须说明输入、输出和适用条件。伪代码表达逻辑,不依赖具体编译器。本课程过程示例除明确列出的C文件外均为伪代码。O(n)描述规模增长时工作量的上界阶,不是精确秒数。常见阶为常数、对数、线性、n log n、平方。额外空间只计辅助存储还是含输入,应先说明。

递归是函数调用自身,必须有基本情形和趋近它的度量。每层调用保留局部状态,深度会占栈空间,递归不会天然更快。

为什么成立 · 关键推导

求最大值:若数组空则返回“无最大值”;否则max←a[0],从i=1到n−1比较并更新。循环不变式:处理完下标i后,max是前i+1项最大值。递归阶乘:fact(0)=1;n>0时fact(n)=n×fact(n−1),n必须非负且结果未溢出。

入门例题 / 1

[3,1,4,4]依次比较,max为3→3→4→4,3次比较,时间O(n)、额外空间O(1)。重复最大值不影响值结果,但求“全部位置”要另存索引。

典型应用与变式 / 2

fact(3)展开3×fact(2)→3×2×fact(1)→3×2×1×fact(0),再回收得6。时间O(n),调用栈O(n);迭代累乘额外空间可为O(1)。

停一下,自己试一试

先独立作答;卡住时看提示,完成后再对照解析。

概念判断

O(n²)是否表示每个输入都恰好执行n²步?

需要一点提示

阶忽略常数与低阶项。

查看过程、答案与错因

不是,也可能是3n²+2n等上界,还须说明最好/平均/最坏情形。

计算与执行过程

双循环i=1到n,内层j=1到i,执行次数?

需要一点提示

求1+2+…+n。

查看过程、答案与错因

n(n+1)/2,量级O(n²)。不能因为内层上界变化就说O(n)。

条件与错误辨析

递归f(n)=f(n)为什么无法正常结束?

需要一点提示

度量是否减少?

查看过程、答案与错因

没有更小子问题,也没有能到达的终止分支,会反复调用直至资源耗尽。

继续实践 · 工具与示范

先按图示和正文用纸笔追踪,再阅读以下伪代码。箭头←为赋值,“若”为条件,“当”为循环;不是可直接编译的C。

max(a,n):
  若 n=0:返回“无最大值”
  best ← a[0]
  对 i=1 到 n−1:
    若 a[i]>best:best ← a[i]
  返回 best

带走这一句

算法要同时回答:算什么、为何对、何时停、要多少资源。

06 / 算法与线性结构:让步骤可执行 · 小节 2

顺序表与链表:搬元素还是改指针

读完这一节,你会

逐步执行两种存储结构的插删,选择合适实现。

大纲要求的教学展开 · 技术讲解 · 本节来源与考点

前置知识:算法、复杂度与递归 · 符号回看

从一个问题开始

队伍中间插一个人,数组和链表为什么付出的工作不同?

插入节点:先接后继,再接前驱

插入节点:先接后继,再接前驱。步骤文字在图下。ABCS
1 / 3

原链表A→B→C,新节点S尚未接入。

原创教学示意 · 手动播放,可随时暂停;折叠或离开小节时停止。

把这件事讲清楚

线性表是有序元素序列的逻辑结构;顺序表连续存储,按下标O(1)访问,中间插删需移动;链表通过指针连接,查第i个一般O(n)。已知前驱节点时,单链表插删可O(1),但寻找位置的时间不能漏算。链表额外保存指针,缓存局部性通常不如数组。带头节点可统一首元素操作,头节点不必存业务数据。

为什么成立 · 关键推导

数组位置i插入v:检查容量→从尾向右搬移→a[i]←v→长度加1。链表在p后插入s:先s.next←p.next,再p.next←s,顺序反了会丢原后继。删除p后q:保存q←p.next→p.next←q.next→释放q。需检查q存在。

入门例题 / 1

[2,5,8]在下标1插4:先8右移,再5右移,写4,得[2,4,5,8]。若从左往右移会覆盖未保存的数据。

典型应用与变式 / 2

A→B→C在A后插S:先S→B,再A→S,得到A→S→B→C。删除B须先找到其前驱S;只持有B地址时不能一般性地声称O(1)完成所有单链表删除情形。

停一下,自己试一试

先独立作答;卡住时看提示,完成后再对照解析。

概念判断

链表按下标访问一定比数组快吗?

需要一点提示

能否直接算第i项地址?

查看过程、答案与错因

不能。数组通常O(1),单链表需沿next走,最坏O(n)。

计算与执行过程

A→B→C删除B,写出修改的指针。

需要一点提示

先定位前驱A。

查看过程、答案与错因

q←A.next即B;A.next←q.next即C;释放q。A→C,不能先释放B再读B.next。

条件与错误辨析

空表删除首元素要检查什么?

需要一点提示

首节点是否存在?

查看过程、答案与错因

检查头指针或头节点next不为空;不存在则返回失败/空结果,不能解引用NULL。

继续实践 · 工具与示范

先按图示和正文用纸笔追踪,再阅读以下伪代码。箭头←为赋值,“若”为条件,“当”为循环;不是可直接编译的C。

insert_after(p,s):
  要求 p,s 有效且 s 不在链中
  s.next ← p.next
  p.next ← s
remove_after(p):
  q ← p.next
  若 q 为空:返回失败
  p.next ← q.next
  保存结果,再释放由本表拥有的 q

对照完整 C / SQL 示例与语法说明 →

带走这一句

选择结构时,把“找到位置”和“修改位置”分开算。

06 / 算法与线性结构:让步骤可执行 · 小节 3

栈与队列:不同的出场顺序

读完这一节,你会

手工模拟入栈出栈和队列,理解它们在程序中的用途。

大纲要求的教学展开 · 技术讲解 · 本节来源与考点

前置知识:顺序表与链表:搬元素还是改指针 · 符号回看

从一个问题开始

撤销最后一次操作与按到达顺序叫号,能用同一种出队规则吗?

先进先出的队列

先进先出的队列。步骤文字在图下。A位置 0B位置 1位置 2队头
1 / 3

入A、B:队头A先到。

原创教学示意 · 手动播放,可随时暂停;折叠或离开小节时停止。

把这件事讲清楚

栈后进先出LIFO,常用于递归、括号匹配、撤销;队列先进先出FIFO,用于排队和广度优先。栈只有栈顶可直接进出。循环队列用取模让下标绕回:next=(index+1)%capacity。若预留一格区分空满,空条件front=rear,满条件(rear+1)%capacity=front,实际容量比数组长度少1;也可另设计数,但条件应随实现改变。

为什么成立 · 关键推导

括号匹配:遇左括号压栈;遇右括号先检查栈非空且顶类型匹配,再弹出;结束时栈必须空。队列入队写rear后前移,出队读front后前移。每步先判断满/空。

入门例题 / 1

依次压入1、2,弹出得到2;再压3,弹出3、1。入栈序列保持,出栈序列受中间弹出时机影响。

典型应用与变式 / 2

长度5预留一格,front=3,rear=1,元素数(1−3+5)%5=3,位置3、4、0有效;再入队写位置1,rear变2,此时(2+1)%5=3等于front,队满。

停一下,自己试一试

先独立作答;卡住时看提示,完成后再对照解析。

概念判断

“([)]”左右括号数量相同就匹配吗?

需要一点提示

栈顶要求就近配对。

查看过程、答案与错因

不匹配。读到)时栈顶是[,类型不符。计数不能检测嵌套顺序。

计算与执行过程

队列入A、B,出一个,再入C,后续出队顺序?

需要一点提示

先进先出。

查看过程、答案与错因

第一次出A,余B;入C后依次B、C。

条件与错误辨析

预留一格的长4循环队列最多存4项吗?

需要一点提示

空满判定占了一格。

查看过程、答案与错因

最多3项;若要存4项须换用计数或满标志,并相应修改条件。

继续实践 · 工具与示范

先按图示和正文用纸笔追踪,再阅读以下伪代码。箭头←为赋值,“若”为条件,“当”为循环;不是可直接编译的C。

match(text):
  栈 S ← 空
  逐字符 c:
    若 c 为左括号:push(S,c)
    若 c 为右括号:
      若 S 为空或栈顶类型不匹配:返回假
      pop(S)
  返回 S 为空

带走这一句

栈关心最近一步,队列关心最早到达。

06 / 算法与线性结构:让步骤可执行 · 小节 4

串、数组与稀疏矩阵

读完这一节,你会

看懂字符串匹配过程和节省存储的条件。

大纲要求的教学展开 · 技术讲解 · 本节来源与考点

前置知识:栈与队列:不同的出场顺序 · 符号回看

从一个问题开始

一个百万行矩阵只有千个非零数,仍要把所有零存下来吗?

把这件事讲清楚

串是字符序列,子串连续,子序列可跳过。朴素模式匹配在每个起点逐字符比较,最坏O(nm)。KMP利用模式自身前后缀信息,失配时保留已知匹配关系,时间O(n+m),不必把主串指针退回。不同next或前缀函数定义有不同下标约定,必须先写定义。

二维数组按行优先时,a[i][j]偏移为(i×列数+j)×元素大小。稀疏矩阵可按(行,列,值)三元组存非零项,另存尺寸与数量;适合零很多但索引元数据也有成本。

为什么成立 · 关键推导

定义前缀函数π[i]为模式0…i的最长相等真前缀/后缀长度,“真”表示不能用整个串。模式ABAB的π=[0,0,1,2]。若已匹配ABAB后失配,可保留长度2的AB,从较短候选继续,不重查主串前两位。

入门例题 / 1

主串ABABC、模式ABC。朴素在0匹配AB后遇A≠C失败,起点1首字符B失败,起点2匹配成功。0起始返回2。

典型应用与变式 / 2

3×4按行数组,每项4字节,a[2][1]偏移(2×4+1)×4=36字节。矩阵(050007)\begin{pmatrix}0&5&0\\0&0&7\end{pmatrix}只存(0,1,5)、(1,2,7)及2×3尺寸,转置时交换行列并按需要重新排序。

停一下,自己试一试

先独立作答;卡住时看提示,完成后再对照解析。

概念判断

“AC”是“ABC”的子串吗?

需要一点提示

是否连续?

查看过程、答案与错因

不是子串,是子序列。模式匹配题若没说子序列,不能跳过B。

计算与执行过程

求AAAA的前缀函数π。

需要一点提示

每个前缀排除自身。

查看过程、答案与错因

[0,1,2,3];最后最长真前后缀AAA长3。

条件与错误辨析

所有矩阵都适合三元组存储吗?

需要一点提示

每项还保存两个坐标。

查看过程、答案与错因

不适合。稠密矩阵可能因坐标开销更大且访问更慢,应根据非零比例和操作模式选择。

继续实践 · 工具与示范

先按图示和正文用纸笔追踪,再阅读以下伪代码。箭头←为赋值,“若”为条件,“当”为循环;不是可直接编译的C。

prefix(pattern):
  若模式空:返回空表
  pi[0] ← 0
  对 i=1 到 m−1:
    j ← pi[i−1]
    当 j>0 且 pattern[i]≠pattern[j]:j ← pi[j−1]
    若 pattern[i]=pattern[j]:j ← j+1
    pi[i] ← j
  返回 pi
空模式在查找中的结果须另定,本课约定匹配位置0。

带走这一句

表示法服务于操作;少存数据并不自动更快。

章末 / 把知识接起来

综合训练

原创综合训练

为括号串([])描述栈过程;为叫号选择结构;把单链表A→B在A后插入S;写各操作的边界。

需要一点提示

看后进先出、先进先出和指针修改顺序。

查看过程、答案与错因

括号:压(、压[、遇]弹[、遇)弹(,最终空栈;叫号用队列。插入先S.next=B再A.next=S。栈弹出须非空,队列须查空满,链表p有效且新节点分配成功;寻找p时间单算。

一点一点,积累下来。

今日学习

00:00:00

累计学习

00:00:00

学习天数

0 天

点击“开始计时”后累计时间。同一科目内切换章节或刷新会接续;切换科目不会自动启动另一科。仅当前获得焦点的可见页面累计,离开、关闭或休眠期间不补计。两科的时间与成就分别保存。

记录保存在当前浏览器,关闭后仍保留;清除网站数据会删除记录。每天累计满 1 分钟记为一个学习日,不要求连续打卡。

学习成就

已达成 0 / 10

成就记录投入与阅读进展,不代表掌握程度。阅读类成就随已读标记更新,撤销标记后会重新计算。