考研408数据结构第三章(栈、队列和数组)核心易错点深度解析

一、栈(Stack)的易错点与解题技巧

1.1 栈的基本操作陷阱

定义 :后进先出(LIFO)的线性表,仅允许在栈顶插入(push)和删除(pop)。
易错点

  • 栈空时执行pop操作:未检查栈空直接弹出元素,导致内存错误或数据异常。
  • 栈满时执行push操作:固定大小的顺序栈未判断栈满,引发数据覆盖。

错误代码示例

c 复制代码
// 错误:未检查栈空直接pop
int Pop(SqStack *S) {
    return S->data[S->top--]; // 当top=-1时越界访问
}

正确解法

c 复制代码
int Pop(SqStack *S, int *e) {
    if (S->top == -1) return 0; // 栈空检查
    *e = S->data[S->top--];
    return 1;
}

真题示例

(2022年408真题) 若入栈序列为a,b,c,d,e,则不可能的出栈序列是?

A. a,b,c,d,e

B. e,d,c,b,a

C. a,e,d,c,b

D. d,c,e,a,b
答案 :C、D
解析:选项C中a最先出栈,说明后续操作均在空栈进行,但第二个出栈元素e不可能在a之后立即弹出。


1.2 共享栈设计误区

定义 :两个栈共享同一存储空间,栈底分别位于数组两端。
易错点

  • 栈满判断错误 :误用top1 == top2作为栈满条件(正确条件应为top1 + 1 == top2)。
  • 初始化设置不当:未正确设置初始指针位置(栈1的top1初始为-1,栈2的top2初始为MAXSIZE)。

正确实现

c 复制代码
typedef struct {
    int data[MAXSIZE];
    int top1 = -1;          // 栈1指针
    int top2 = MAXSIZE;     // 栈2指针
} SharedStack;

int Push(SharedStack *S, int stackNum, int e) {
    if (S->top1 + 1 == S->top2) return 0; // 栈满
    if (stackNum == 1)
        S->data[++S->top1] = e;
    else
        S->data[--S->top2] = e;
    return 1;
}

二、队列(Queue)的高频易错点

2.1 循环队列的判空与判满

定义 :通过取模运算实现空间复用的队列。
易错点

  • 队空与队满混淆 :使用rear == front判断队空时,队满条件应为(rear+1)%MAXSIZE == front
  • 指针更新顺序错误:先移动指针再存数据,导致数据覆盖。

错误代码示例

c 复制代码
// 错误:未正确处理队满条件
void EnQueue(SqQueue *Q, int e) {
    Q->data[Q->rear] = e;
    Q->rear = (Q->rear+1) % MAXSIZE; // 若此时rear追上front,队满无法检测
}

正确解法

c 复制代码
int EnQueue(SqQueue *Q, int e) {
    if ((Q->rear + 1) % MAXSIZE == Q->front) return 0; // 队满
    Q->data[Q->rear] = e;
    Q->rear = (Q->rear + 1) % MAXSIZE;
    return 1;
}

真题示例

(2023年408真题) 设循环队列容量为50,front指向队头元素,rear指向队尾元素的下一个位置。若front=12,rear=5,则队列中元素个数为?
答案 :(5 - 12 + 50) % 50 = 43
解析 :元素个数计算公式为(rear - front + MAXSIZE) % MAXSIZE


2.2 链式队列的指针处理

定义 :使用链表实现的队列,需维护头指针(front)和尾指针(rear)。
易错点

  • 删除节点后未释放内存:导致内存泄漏。
  • 队列空时未重置尾指针:删除最后一个元素后,rear未置空,后续操作出错。

错误代码示例

c 复制代码
// 错误:删除最后一个元素后未重置rear
int DeQueue(LinkQueue *Q, int *e) {
    if (Q->front == Q->rear) return 0;
    QNode *p = Q->front->next;
    *e = p->data;
    Q->front->next = p->next;
    free(p);
    return 1;
}

正确解法

c 复制代码
int DeQueue(LinkQueue *Q, int *e) {
    if (Q->front == Q->rear) return 0;
    QNode *p = Q->front->next;
    *e = p->data;
    Q->front->next = p->next;
    if (p == Q->rear) Q->rear = Q->front; // 删除最后一个节点时重置rear
    free(p);
    return 1;
}

三、数组与特殊矩阵的压缩存储

3.1 多维数组地址计算

行优先公式
LOC(a[i][j]) = LOC(a[0][0]) + (i * n + j) * L
列优先公式
LOC(a[i][j]) = LOC(a[0][0]) + (j * m + i) * L

易错点

  • 下标起始错误:混淆数组下标从0还是1开始。
  • 维度混淆:将行数m和列数n颠倒。

真题示例

(2021年408真题) 二维数组A[0...9][0...9]按行优先存储,每个元素占2B,首地址为200。则A[6][8]的地址为?
答案 :200 + (6*10 + 8)2 = 200 + 68 2 = 336
解析:行优先计算偏移量时,每行有10个元素(0-9)。


3.2 对称矩阵压缩存储

压缩策略 :仅存储主对角线及以下元素,总元素数n(n+1)/2
地址计算(行优先)

  • 当i ≥ j时,k = i*(i+1)/2 + j
  • 当i < j时,k = j*(j+1)/2 + i

易错点

  • 公式应用错误:将行优先公式用于列优先存储。
  • 索引越界:未检查i和j的大小关系直接计算。

3.3 稀疏矩阵三元组表示法

定义 :使用(row, col, value)存储非零元素。
易错点

  • 未按行优先排序:快速转置算法要求三元组按列有序。
  • 未处理重复元素:矩阵加法时相同位置元素需合并。

真题示例

(2020年408真题) 稀疏矩阵快速转置算法的时间复杂度为?
答案 :O(nu + tu),其中nu为列数,tu为非零元素个数。
解析:需先统计每列非零元素数,再计算起始位置。


四、应用场景中的典型错误

4.1 括号匹配问题

错误场景 :仅考虑圆括号,忽略其他类型括号(如{}、[])。
正确实现

c 复制代码
bool BracketCheck(char *str) {
    SqStack S;
    InitStack(&S);
    for (int i = 0; str[i] != '\0'; i++) {
        if (str[i] == '(' || str[i] == '[' || str[i] == '{') 
            Push(&S, str[i]);
        else {
            if (StackEmpty(S)) return false;
            char topElem;
            Pop(&S, &topElem);
            if ((topElem == '(' && str[i] != ')') || 
                (topElem == '[' && str[i] != ']') || 
                (topElem == '{' && str[i] != '}')) 
                return false;
        }
    }
    return StackEmpty(S);
}

4.2 递归调用栈溢出

错误场景 :未设置递归终止条件,或递归深度过大。
示例

c 复制代码
// 错误:无终止条件的递归
void InfiniteRecursion(int n) {
    InfiniteRecursion(n + 1); // 导致栈溢出
}

五、总结与复习策略

5.1 高频易错点总结

数据结构 核心易错点 应对策略
栈空判断、共享栈边界处理 所有操作前检查栈状态
队列 循环队列判满、链队指针重置 画图分析指针移动轨迹
数组 下标计算、压缩公式应用 记忆行/列优先公式并代入验证
应用问题 括号类型遗漏、递归终止条件缺失 设计测试用例覆盖边界情况

5.2 备考建议

  1. 手写代码训练:每日至少完成3道栈/队列算法题(如LeetCode 232、225题)。
  2. 真题强化:重点练习2015-2023年408真题中第三章相关题目。
  3. 错题归纳:建立错题本,分类记录指针处理、边界条件等错误类型。
  4. 复杂度分析:对每个操作的时间/空间复杂度进行标注,强化应试意识。
相关推荐
_GR1 小时前
2016年蓝桥杯第七届C&C++大学B组真题及代码
c语言·数据结构·c++·算法·蓝桥杯
Buling_01 小时前
算法-二叉树篇26-将有序数组转换为二叉搜索树
数据结构·算法·leetcode
Vacant Seat2 小时前
图论-岛屿数量
java·数据结构·算法·图论
WW_千谷山4_sch2 小时前
MYOJ_7456:输出邻接点的数量(图论概念及基础运用)
数据结构·c++·算法·图论
圆圆滚滚小企鹅。2 小时前
刷题记录 HOT100 图论-2:994. 腐烂的橘子
数据结构·笔记·python·算法·leetcode·图论
人类群星闪耀时2 小时前
巧用优先队列与分治法:高效合并 K 个升序链表
数据结构·windows·链表
屁股割了还要学10 小时前
【计算机网络入门】初学计算机网络(五)
学习·计算机网络·考研·青少年编程
屁股割了还要学10 小时前
【计算机网络入门】初学计算机网络(七)
网络·学习·计算机网络·考研·青少年编程
萌の鱼11 小时前
leetcode 48. 旋转图像
数据结构·c++·算法·leetcode
win水12 小时前
数据结构(初阶)(七)----树和二叉树(堆,堆排序)
数据结构