期末复习,408考研数据结构:第一章绪论完整知识梳理与真题深度解读

前言

数据结构是计算机专业考研 408 统考的重中之重,而第一章"绪论"虽然不涉及具体的代码实现,却是整本教材的"地基"。很多同学在复习初期容易忽视这一章,直接去背链表、二叉树。等到做选择题时,往往会在"ADT的定义"、"逻辑结构与存储结构的区别"、"时间复杂度的精确计算"上频频丢分。

这篇文章做了什么? 我完全结合 408 考纲和王道考研教材(1.1 节与 1.2 节),为你完整梳理了第一章的所有核心考点:

  • 微观与宏观:理清数据、数据元素、数据项之间的层级关系。
  • 三要素剖析:深度解析逻辑结构、存储结构以及它们与算法设计之间的黄金法则。
  • 算法效率评价:从大 O 表示法,到极易混淆的时间复杂度推导(如:递归、嵌套循环的复合计算),再到空间复杂度的底层逻辑。
  • 真题实战:本书精选了 2012-2025 年的 408 统考经典真题进行细致拆解,帮你看透出题人的"陷阱"。

吃透这一章,你不仅能拿稳基础分,更能为后续"线性表、树、图"的高难度算法学习,打下坚实的理论基础。

下面,我们正式开始!

1. 数据结构的基本概念

1.1 基本概念和术语

在理解数据结构之前,必须分清以下几个对象之间的大小层级关系:

1. 核心概念层级(由大到小)

  • 数据(Data):信息的载体,是描述客观事物属性的数、字符及所有能输入到计算机并被程序处理的符号集合。它是计算机程序加工的原料。
  • 数据对象(Data Object):具有相同性质的数据元素的集合,是数据的子集(例如:整数数据对象 N={0,±1,±2,...})。
  • 数据元素(Data Element):数据的基本单位。在程序中通常作为一个整体进行考虑和处理(例如:一条"学生记录")。
  • 数据项(Data Item):构成数据元素的不可分割的最小单位(例如:"学生记录"中的"学号"、"姓名")。

💡 :数据项是最小单位;数据元素是基本单位;数据对象是集合。

2 数据类型与抽象数据类型(ADT)

在编程语言层面,我们通过类型来约束数据的操作。

  • 数据类型(Data Type) :是一个值的集合以及定义在该集合上的一组操作的总称。
    • 原子类型:值不可再分(例如 int, char)。
    • 结构类型:值可再分解为若干分量(例如 C 语言的 struct)。
  • 抽象数据类型(ADT) :指一个数学模型以及定义在该模型上的一组操作。
    • 核心精髓:ADT 强调"定义与实现相分离"。例如"栈"是一个 ADT,它定义了入栈、出栈操作,但用户不需要知道栈底是用数组(顺序存储)还是链表(链式存储)实现的。

1.2 数据结构的三要素

数据结构 = 逻辑结构 + 存储结构 + 数据的运算。这三者缺一不可,决定了你如何设计算法、如何实现算法。

1. 数据的逻辑结构(设计算法的蓝图)

逻辑结构是指数据元素之间的逻辑关系,它与计算机无关,独立于具体的系统。可分为线性结构和非线性结构两大类:

  • 线性结构 (元素之间存在一对一关系)
    • 包含内容:一般线性表、受限线性表(栈、队列)、线性表推广(串、数组)。
  • 非线性结构 (其余情况)
    • 集合结构:元素之间除了"同属一个集合"外,别无其他关系(结构最松散)。
    • 树形结构:元素之间存在一对多的层次关系(包括一般树和二叉树)。
    • 图状结构/网状结构 :元素之间存在多对多的任意关系(包括有向图和无向图)。

2 数据的存储结构(算法实现的具体手段)

存储结构 是指逻辑结构在计算机内存中的物理表示,它依赖于具体的编程语言。共有四种最经典的存储方式:

存储方式 实现原理 优点 缺点(常考陷阱)
顺序存储 逻辑相邻的元素,物理位置也相邻(如数组)。 1. 可实现随机存取(按索引 O(1) 访问) 2. 空间利用率极高(无指针开销)。 1. 需要连续的存储空间 2. 容易产生外部碎片(无法利用的零散空间) 3. 插入删除需移动大量元素。
链式存储 逻辑相邻的元素,物理位置不一定相邻,靠指针串联(如链表)。 1. 不需要连续空间,无碎片问题 2. 插入删除非常灵活。 1. 只能进行顺序存取(必须从头遍历) 2. 每个元素因存储指针需要额外占用空间。
索引存储 额外建立一张索引表,通过关键字在索引中查找地址。 检索速度快。 1. 需要额外的索引表空间 2. 数据更新时,需要同步更新索引表,带来额外时间开销。
散列存储 根据元素关键字直接计算出存储地址(哈希表)。 检索、插入、删除的速度都非常快。 散列函数设计不当会产生哈希冲突,解决冲突会带来额外的时间和空间开销。

3 数据的运算

数据的运算包含两个分离的层面:

  • 运算的定义:针对逻辑结构,说明运算的功能(例如:栈的出栈操作功能是弹出栈顶元素)。
  • 运算的实现 :基于存储结构,描述运算的具体操作步骤(例如:如果用顺序表实现,出栈就是 top--;如果用链表实现,出栈就是 head = head->next)。

"算法的设计取决于所采用的逻辑结构,而算法的实现则依赖于所选择的存储结构。"

💡 实战联想

  • 逻辑设计时:思考"我该用栈(一对一)来处理,还是用二叉树(一对多)来高效查找?" ------ 这是设计层面。
  • 代码实现时:选定二叉树后,我"是用数组(顺序存储)建树,还是用指针(链式存储)建树?" ------ 这将直接决定你最终写出来的代码有多复杂、运行有多快,这是实现层面。

2. 算法和算法评价

2.1 算法的基本概念

1. 算法的定义

算法(Algorithm) 是对特定问题求解步骤的描述。它是指令的有限序列,其中的每一条指令表示一个或多个操作。

2. 算法的五个重要特性(⚠️ 选择题高频判据)

一个"有效的算法"必须同时具备以下 5 个特性:

  • 有穷性:算法必须在执行有限步之后结束,且每一步都能在有限时间内完成。(无法终止的不能叫算法)
  • 确定性:算法中每条指令必须有明确的含义,对于相同的输入,只能产生相同的输出。(不能有二义性)
  • 可行性:算法中所描述的操作,都可以通过已经实现的基本运算执行有限次来完成。
  • 输入:算法可以有零个或多个输入,这些输入取自某个特定对象的集合。
  • 输出:算法至少有一个输出,且该输出与输入之间存在某种特定关系。

3. "好"算法的评判标准(设计目标)

除了基本特性,设计一个"好"的算法还应满足以下 4 个目标:

  • 正确性:能正确地解决所给问题(最基础)。
  • 可读性:结构清晰、易于理解,便于阅读和交流(好算法要让人看得懂)。
  • 健壮性:对非法或异常输入能做出适当处理,而不是产生不可预测的结果(如直接崩溃)。
  • 高效率与低存储量需求:效率指算法的执行时间尽量短;存储量指执行过程中所需的最大存储空间尽量小。这两个与"问题规模"密切相关。

2.2 算法效率的度量

在实际应用中,正确性只是基础,效率才是衡量算法优劣的关键指标。由于实际运行时间受硬件、编译器等多种因素影响,无法用绝对时间作为通用标准,因此引入了渐进复杂度分析。

(一)时间复杂度(T(n))

1. 定义

时间复杂度描述算法执行时间随问题规模 n 增大而变化的趋势,是关于 n 的渐近函数。通常通过语句频度(某条语句执行次数)来衡量。设算法中所有语句频度之和为 T(n),它就是问题规模 n 的函数。

💡 核心推导法则:当 n 足够大时,低阶项和常数系数对整体增长趋势的影响可以忽略不计,因此只需关注 T(n) 中增长最快的项。该项通常由算法中的基本运算(最深层循环内的关键操作)的执行次数决定,该执行次数的数量级即为整个算法的时间复杂度。

2. 大 O 记号表示法

若存在正常数 C 和 n₀,使得对所有 n ≥ n₀,都有:0 ≤ T(n) ≤ C × f(n),则称 T(n) = O(f(n))。它表示当 n 足够大时,T(n) 的增长速度不超过 f(n) 的常数倍。

3. 三种情况分析

算法的实际执行时间,不仅依赖于问题规模 n,还受输入数据初始状态的影响。以在数组 A0...n-1 中逆序查找值 k 为例:

  • 最好时间复杂度:最有利情况。例如 An-1 == k,基本运算执行 1 次,时间复杂度为 O(1)。
  • 最坏时间复杂度:最不利情况。例如 k 根本不存在,基本运算执行 n 次,时间复杂度为 O(n)。
  • 平均时间复杂度:所有输入等概率出现时的期望执行时间。

⚠️ 考试标准:通常情况下,以最坏时间复杂度作为算法效率的评价标准,因为它提供了运行时间的确定性上界。

4. 时间复杂度推导的两大"黄金规则"
  • 加法规则:若两段代码顺序执行,则总时间复杂度取两者中的高阶项。O(f(n)) + O(g(n)) = O(max(f(n), g(n)))
  • 乘法规则:若一段代码嵌套在另一段内部,则总时间复杂度为两者之积。O(f(n)) × O(g(n)) = O(f(n) × g(n))

实战示例:假设代码块 a、b、c 的时间复杂度分别为 O(1)、O(n)、O(n²)。

  • 顺序结构(代码a执行完再执行b和c):时间复杂度 = O(1) + O(n) + O(n²) = O(n²)(加法规则,取最大项)。
  • 嵌套结构(代码a套着b,b套着c):时间复杂度 = O(1) × O(n) × O(n²) = O(n³)(乘法规则。
5. 常见的时间复杂度阶(按增长速度由慢到快排序)

O(1) < O(log n) < O(n) < O(n log n) < O(n²) < O(n³) < O(2ⁿ) < O(n!) < O(nⁿ)

在 408 真题中,通常会要求你根据算法的复杂度判断其是否能应对 10⁵ 级别的数据量(通常 O(n²) 会超时,必须降到 O(n log n))。

(二)空间复杂度(S(n))

1. 定义

空间复杂度 S(n) 表示算法在运行过程中所需的额外存储空间,它是问题规模 n 的函数,记为:S(n) = O(g(n))

2. 空间占用辨析(极易混淆的考点)

程序执行时所需的空间包括三部分:

  • 指令、常数和变量:这部分空间与 n 无关。
  • 输入数据 :这部分空间取决于问题本身,与算法无关。注意:在分析空间复杂度时,我们通常不计入输入数据所占的空间。
  • 辅助空间:算法运行过程中额外使用的空间(如递归调用栈、临时数组、指针等)。

🌟 考研标准:我们在分析空间复杂度时,只关注算法额外使用的辅助空间。

3. 原地工作(原地算法)

若算法仅使用常量级的额外空间 ,即空间复杂度为 S(n) = O(1),则称该算法为原地工作(In-place)

  • 举例:快速排序如果不使用递归栈,而是用迭代方式在原数组上进行交换,就是原地工作。
  • 如果算法创建了与输入规模 n 同阶的辅助数组,则其空间复杂度为 O(n)。

3.相关例题以及408真题讲解

例题 1:嵌套循环的时间复杂度推导

正确答案:A

代码示例

c 复制代码
for(i=1; i<=n; i++) {
    for(j=1; j<=2*i; j++) {
        m++;  // 基本运算
    }
}

第一步:理清循环的嵌套关系

  • 外层循环for(i=1; i<=n; i++),变量 i 的取值依次为:1, 2, 3, ..., n(共执行 n 轮)。
  • 内层循环for(j=1; j<=2*i; j++),它的循环次数取决于当前外层变量 i 的值,每次执行 2×i 次。

第二步:手动推算前几次,找规律

我们可以把 i 代入,看看划线语句 m++; 会执行多少次:

  • 当 i=1 时:内层循环 j 从 1 到 2×1,即执行 2 次。
  • 当 i=2 时:内层循环 j 从 1 到 2×2,即执行 4 次。
  • 当 i=3 时:内层循环 j 从 1 到 2×3,即执行 6 次。
  • ...
  • 当 i=n 时:内层循环 j 从 1 到 2×n,即执行 2n 次。

第三步:用数学求和公式计算总次数

我们要计算的总执行次数,就是上面这一串数字相加:

复制代码
执行次数 = 2 + 4 + 6 + ⋯ + 2n

怎么求和?提取公因数 2:

复制代码
= 2 × (1 + 2 + 3 + ⋯ + n)

代入中学学过的等差数列求和公式(首项加末项乘以项数除以2):

复制代码
(1 + 2 + 3 + ⋯ + n) = n(n+1)/2

最终结果

复制代码
2 × n(n+1)/2 = n(n+1)

第四步:转化为大 O 表示法

当 n 足够大时,n(n+1) = n² + n,其中增长最快的项是 n²。因此,该算法的时间复杂度为 O(n²)

例题 2:时间复杂度

正确答案:C. O(log₂n)

很多同学做错这道题,是因为误以为代码里的 2 * Func(n/2) 是产生了两个递归分支。下面我为你详细拆解底层的推导逻辑:

第一步:写出递归方程(时间复杂度递推式)

我们来分析代码的执行过程:

  • 如果 n == 1,直接返回,这是基本操作,耗时 O(1)。
  • 如果 n > 1,代码执行 return 2 * Func(n/2) + n;

🔴 核心注意(极易看错的地方)2 * Func(n/2) 这里的 2 * 是普通的乘法运算,不是递归调用 。真实的递归调用只有 Func(n/2)1 次。整个语句中,除了递归调用,剩下的"乘以 2"、"加 n"、"返回"都是基本算术运算,花费的是常数时间 O(1)。

所以,该算法的时间复杂度递推公式为:

复制代码
T(n) = T(n/2) + O(1)

第二步:分析递归深度(到底执行了多少层?)

根据公式,每递归一次,问题规模 n 就会除以 2:

  • 第 1 层:处理规模 n
  • 第 2 层:处理规模 n/2
  • 第 3 层:处理规模 n/4
  • ...
  • 直到:处理规模 1(触发 n==1 的结束条件)

我们要找到一个 k,使得 n 除以 k 次 2 后等于 1,即:

复制代码
n / 2ᵏ = 1  ⇒  2ᵏ = n  ⇒  k = log₂n

也就是说,这个函数会递归嵌套 log₂n 层。

第三步:计算总的执行时间

每一层消耗的时间都是常数 O(1)。整个递归共有 log₂n 层。

所以,总的时间复杂度 = 层数 × 每层消耗 = log₂n × O(1) = O(log₂n)

例题 3 (408真题)

正确答案:B. O(n)

结合你上一问刚刚搞懂的"减半递归",这道题正好是另一类经典的"线性递归",把它们放在一起对比,你的时间复杂度分析能力就能彻底过关了!下面我为你详细推导这道题的逻辑,以及它与上一题的本质区别。

第一步:写出递归方程(递推式)

我们看一下代码的执行过程:

  • 终止条件 :当 n ≤ 1 时,直接返回 1,执行一次基本判断,耗时 O(1)。
  • 递归步骤return n * fact(n-1);。这里有一个乘法运算 n * ...,加上一次递归调用 fact(n-1)

所以,这个函数的时间复杂度递推公式为:

复制代码
T(n) = T(n-1) + O(1)

第二步:展开计算总执行次数

我们可以把递归一层一层"展开"来看:

  • 第 1 层:处理规模 n,花费 1 个单位时间(做判断和乘法),然后去调用 n-1。
  • 第 2 层:处理规模 n-1,花费 1 个单位时间,然后去调用 n-2。
  • 第 3 层:处理规模 n-2,花费 1 个单位时间,然后去调用 n-3。
  • ...
  • 第 n 层:处理规模 1(触发 n<=1 结束递归),花费 1 个单位时间。

因为 n 每次只减少 1,所以总共会递归嵌套 n 层。

总的执行时间 = 层数 × 每层耗时 = n × 1。

所以,时间复杂度为 O(n)

💡 金牌对比:这道题和上一题(例题 2)的区别!

很多同学会把这道题和上一题弄混,因为它们都是"递归代码 + 乘法"。你仔细对比:

  • 上一题的代码return 2*Func(n/2)+n;,参数是 n/2

    • 数学过程:n → n/2 → n/4 → ... → 1。这个下降速度极快,只需要 log₂n 步就能到底。
    • 时间复杂度:O(log₂n)(对数级)
  • 这一题的代码return n*fact(n-1);,参数是 n-1

    • 数学过程:n → n-1 → n-2 → ... → 1。这个下降速度很慢,必须要一步一步踩到底,需要 n 步。
    • 时间复杂度:O(n)(线性级)

🚨 408 考场秒杀口诀 :遇到递归求时间复杂度,不需要看乘除法,只看递归参数的缩小速度

  • 参数加减 :每次 n-1 (或 n-k) ➡️ 这是 O(n)
  • 参数乘除 :每次 n/2 (或 n/3) ➡️ 这是 O(log n)

例题 4 (408真题)

正确答案:C. O(n log₂n)

这道题是 408 考研中非常经典的"循环嵌套求时间复杂度"题型。只要掌握了"外层循环计算次数"和"内层循环计算次数"的乘除关系,就能秒杀这类题目。我为你详细拆解推导过程:

第一步:分别分析外层和内层循环的执行次数

🔵 内层循环(for(j=1; j<=n; j++)

不管外面的 k 是多少,内层变量 j 始终是从 1 循环到 n。所以,内层循环每完整执行一次,时间复杂度是 O(n)(执行了 n 次 count++)。

🔴 外层循环(for(k=1; k<=n; k*=2)

外层变量 k 的取值变化是:1, 2, 4, 8, ...,每一次都乘以 2。我们要找到 k 能取到的最大的值,即 2ˣ ≤ n。解这个不等式:x ≤ log₂n。所以,外层循环一共执行了 log₂n 次。

第二步:将两者用乘法规则结合

因为内层循环是完全包含在外层循环里面的(有嵌套关系),所以我们要用之前总结的 "乘法规则"

总时间复杂度 = 外层循环执行次数 × 内层循环执行次数

= log₂n × O(n)

= O(n log₂n)

所以直接对应选项 C

例题 5(408真题)

**正确答案:B. O(n¹/²)

这道题非常经典,它最大的陷阱在于:虽然只有一个 while 循环,但它的循环变量 sum 增长的速度是越来越快的,而不是恒定的。很多同学会误选 C(O(n)),就是因为习惯了 i++ 这种一次加 1 的循环。下面我为你详细拆解它的底层数学推导,你算过一次就永远不会再掉进这个陷阱。

第一步:拆解 sum += ++i; 的执行过程

这个语句非常关键。++i 是前置自增(先加 1,再取值),然后累加到 sum 上。我们列一个表格看看第 k 次循环时,i 和 sum 的值分别是多少:

  • 第 1 次循环:i 变成了 1,sum = 0 + 1 = 1
  • 第 2 次循环:i 变成了 2,sum = 1 + 2 = 3
  • 第 3 次循环:i 变成了 3,sum = 3 + 3 = 6
  • 第 4 次循环:i 变成了 4,sum = 6 + 4 = 10
  • ...
  • 第 k 次循环:i 变成了 k,sum = 前面所有数的和。

规律:经过 k 次循环后,sum 的值实际上等于前 k 个自然数之和。

第二步:建立数学模型(求解循环次数)

题目中循环的条件是 while(sum < n)。也就是说,循环会在 sum >= n 的时候停止。我们要找出此时经历了几次循环(假设为 k 次)。

根据第一步的规律:

复制代码
1 + 2 + 3 + ⋯ + k ≥ n

利用等差数列求和公式(首项加末项乘以项数除以2):

复制代码
k(k+1)/2 ≥ n

为了求时间复杂度,我们只看渐近趋势(忽略低阶项和常数)。当 n 足够大时,k+1 ≈ k。不等式可以近似为:

复制代码
k²/2 ≈ n  ⇒  k² ≈ 2n  ⇒  k ≈ √(2n)

结论 :这个 while 循环一共会执行 √(2n) 次。

第三步:带入大 O 记号

因为循环体内部 sum += ++i 只是简单的加法运算,属于常数级操作 O(1)。所以整个算法的总时间复杂度 = 循环次数 × 单次操作耗时。

复制代码
T(n) = √(2n) × O(1) = O(√n) = O(n¹/²)

所以对应选项 B

例题 6(408真题)

正确答案:B. O(n)

这道题是嵌套循环的经典变种,很多同学一眼看到外层循环 i*=2 就选了 O(n log n),或者看到内层循环到 i 就选了 O(n²),这两种都是典型的中计了。我为你详细列出最严谨的数学推导过程,帮你彻底打通这个"看似复杂,实则秒杀"的考点。

代码示例

c 复制代码
int sum = 0;
for(int i=1; i<n; i*=2) {
    for(int j=0; j<i; j++) {
        sum++;  // 基本运算
    }
}

第一步:列出内外循环的真实执行次数

🔴 外层循环for(int i=1; i<n; i*=2)

i 的取值依次为:1, 2, 4, 8, ..., 2ᵏ⁻¹。可以算出,外层循环一共执行 log₂n 次(设执行了 k 轮)。

🔵 内层循环for(int j=0; j<i; j++)

它的执行次数完全取决于当前的外层变量 i。内层循环的 sum++ 会执行 i 次。

第二步:逐层累加,找出规律(等比数列求和)

我们把外循环每一轮里,内层 sum++ 的执行次数列出来:

  • 第 1 轮(i=1)时,内层执行 1 次;
  • 第 2 轮(i=2)时,内层执行 2 次;
  • 第 3 轮(i=4)时,内层执行 4 次;
  • ...
  • 第 k 轮(i=2ᵏ⁻¹)时,内层执行 2ᵏ⁻¹ 次。

sum++ 被执行的总次数 = 1 + 2 + 4 + 8 + ⋯ + 2ᵏ⁻¹

这是一个首项为 1,公比为 2 的等比数列。直接套用等比数列求和公式(或者直接死记 1+2+4+⋯+2ᵏ⁻¹ = 2ᵏ − 1):

复制代码
总执行次数 = 2ᵏ − 1

第三步:消除外层变量 k,化为关于 n 的表达式

由于外层循环的结束条件是 i < n,所以最后一轮 i 的值必然满足 2ᵏ⁻¹ < n(也就是 2ᵏ ≤ 2n)。把 2ᵏ ≤ 2n 代入上面的总执行次数式子中:

复制代码
总执行次数 ≤ 2n − 1

结论sum++ 语句在整个程序运行期间,最多只会被执行 2n 次左右。因此,该算法的时间复杂度为 O(n)

💡 为什么绝对不可能是 O(n log n) 或 O(n²)?

  • 为什么不选 O(n²)(D)? 如果是 O(n²),外循环必须是 i++ 跑 n 次,内层也平均跑 n/2 次。本代码的外循环只跑了 log 次,速度远低于线性。
  • 为什么不选 O(n log n)(C)? 很多同学误以为"外循环 log n 次 × 内循环 n 次"就是 n log n,但内层不是每次都能跑满 n 次。随着 i 的增长,内层总和正好抵消了外层的对数缩减。

🎯 考场终极口诀秒杀

"外循环乘2是对数,内层累加一次翻一倍;加起来是等比数列求和,最终算下来就是 O(n)。"

以后做这种外层对数、内层线性增长的嵌套循环时,不要直接乘,一定要列出前几项看看是不是等比数列(或者等差数列),算一次和就能直接得到答案!

例题 7 (408真题)

正确答案:B. O(n)

这又是一道嵌套循环的经典变种题。很多同学在第一眼看到外层循环 i*i<=n 时,容易直接认为是 O(√n);看到内层循环 j<=i,就想当然地认为是 O(n²) 或者 O(n√n),这两种都是常见的错误逻辑。正确的推导逻辑,需要用到等差数列求和。我们一步步来拆解:

第一步:看透外层循环的实际次数

外层循环:for(i=1; i*i<=n; i++)

判断条件 i*i <= n 等价于 i ≤ √n。所以,外层循环变量 i 的取值是:1, 2, 3, ..., ⌊√n⌋。我们假设外层一共执行了 k = √n 次(为了计算方便,忽略向下取整)。

第二步:分析内层循环的规律(千万别直接乘!)

内层循环:for(j=1; j<=i; j++)

内层循环的执行次数完全取决于当前外层的 i 值。

  • 当 i=1 时,count++ 执行 1 次;
  • 当 i=2 时,count++ 执行 2 次;
  • 当 i=3 时,count++ 执行 3 次;
  • ...
  • 当 i=√n 时,count++ 执行 √n 次。

整个程序 count++ 被执行的总次数 = 1 + 2 + 3 + ⋯ + √n

第三步:套用等差数列求和公式得出结论

这是一个首项为1,末项为 √n,项数为 √n 的等差数列。直接套用求和公式:

复制代码
总次数 = (首项 + 末项) × 项数 / 2 = (1 + √n) × √n / 2

展开化简:

复制代码
总次数 = (n + √n) / 2

当 n 趋向于无穷大时,低阶项 √n 和常数系数 1/2 可以忽略不计。所以渐进时间复杂度只剩下了最高阶项 n。

例题 8

!在这里插入图片描述(https://i-blog.csdnimg.cn/direct/9b1daa525ec941e2b75ecb79415

📌 总结

至此,408 数据结构第一章"绪论"的知识点就已经全部打通了!我们回顾一下本章必须死磕的核心要点:

  • 名词辨析要认清:数据项是最小单位,数据元素是基本单位,数据对象是集合;ADT 强调"定义与实现分离"。
  • 结构设计看逻辑,代码实现看存储:记住万能的黄金法则------算法的设计取决于逻辑结构,算法的实现取决于存储结构。
  • 时空复杂度是性价比指标 :时间复杂度的计算,核心是抓住"最高阶项"。针对嵌套循环,要着重识别外层是否是对数级(i*=2i*i),求执行次数要学会用数列求和公式来破解。空间复杂度的计算,一定要记住"不算输入数据,只算额外辅助空间",常数级的额外空间称为"原地工作"。
  • 刷真题的"题感":408 对本章的考察,不仅限于简单的名词解释,更注重时间/空间复杂度的计算推导能力。做这类题时,不要畏惧复杂的数学公式,把循环次数列出来,问题往往就能迎刃而解。

第一章的内容我们就先到这里。作为纲领性的章节,如果你在后续复习"线性表"、"树与二叉树"、"图"的具体算法时,如果对复杂度或者概念有困惑,随时可以回到这篇文章来翻翻看。

如果你觉得这份整理对你有帮助,欢迎点赞、收藏、关注!下一篇,我们将正式进入 "线性表" 的考点深度解析,不见不散!

相关推荐
茯苓gao1 小时前
嵌入式开发笔记:工业机器人通信协议深度解析——从现场总线到工业以太网
笔记·嵌入式硬件·学习·机器人·信息与通信
取地址符2 小时前
Rust语法学习 (基于Rustlings)(1):基础语法
经验分享·笔记·学习·rust
阿文的代码库2 小时前
经典算法题剖析:按奇偶排序数组
数据结构·算法
不会调制解调的猫2 小时前
笔记 | 什么是 rp_filter(反向路径过滤)?
服务器·网络·笔记
星马梦缘2 小时前
ACM CSP竞赛笔记(二十三)——线段树 与 树状数组
笔记·线段树·acm·树状数组·csp
北鸟南游3 小时前
学习-claude code 工程化实战的笔记-极客时间
笔记·学习·ai编程
解局易否结局3 小时前
鸿蒙PC应用开发:窗口管理 + 鼠标键盘交互 + 文件对话框
笔记·华为·计算机外设·交互·harmonyos
三品吉他手会点灯3 小时前
嵌入式机器学习 - 学习笔记1.0.2 - 学习路线导览:从机器学习基础到 TinyML应用
人工智能·笔记·嵌入式硬件·学习·机器学习
xu_wenming4 小时前
Zephyr上开发 BLE(低功耗蓝牙)入门应用
c语言·嵌入式硬件·物联网