Skip to content

共享栈

核心思想

用一个大小为 MaxSize 的数组 data 同时存放两个栈:

  • 栈 1:栈底在下标 0,入栈时 top1 从左向右增长
  • 栈 2:栈底在下标 MaxSize-1,入栈时 top2 从右向左增长

两个栈相向生长,共同利用中间的空闲空间:

下标:  0   1   2   ...       ...  MaxSize-2  MaxSize-1
      [s1  s1  s1] → 空闲区 ← [s2  s2        s2      ]
            ↑ top1                    ↑ top2

数据结构定义:

c
#define MaxSize 10

typedef struct {
    int data[MaxSize];
    int top1;  // 栈1栈顶指针
    int top2;  // 栈2栈顶指针
} SharedStack;

// 初始化
void InitStack(SharedStack *s) {
    s->top1 = -1;           // 栈1为空
    s->top2 = MaxSize;      // 栈2为空
}

初始状态下 top1 = -1top2 = MaxSize,表示两个栈均为空。

交互可视化

通过下方的交互动画,你可以逐步观察共享栈的执行过程:

加载可视化中...

操作详解

入栈操作

入栈前必须先判断栈是否已满。根据操作的栈编号,分别移动对应的栈顶指针并写入元素。

c
// stackNum: 1 表示栈1,2 表示栈2
bool Push(SharedStack *s, int stackNum, int x) {
    if (s->top1 + 1 == s->top2)   // 栈满
        return false;
    if (stackNum == 1)
        s->data[++s->top1] = x;   // 栈1:指针右移后入栈
    else
        s->data[--s->top2] = x;   // 栈2:指针左移后入栈
    return true;
}

关键步骤:

  1. 判断栈满条件 top1 + 1 == top2
  2. 栈 1 入栈:先 top1++,再赋值
  3. 栈 2 入栈:先 top2--,再赋值

出栈操作

出栈前先判断对应的栈是否为空,然后取出栈顶元素并移动指针。

c
bool Pop(SharedStack *s, int stackNum, int *x) {
    if (stackNum == 1) {
        if (s->top1 == -1)        // 栈1空
            return false;
        *x = s->data[s->top1--];  // 取值后指针左移
    } else {
        if (s->top2 == MaxSize)   // 栈2空
            return false;
        *x = s->data[s->top2++];  // 取值后指针右移
    }
    return true;
}

关键步骤:

  1. 栈 1 判空:top1 == -1
  2. 栈 2 判空:top2 == MaxSize
  3. 出栈方向与入栈方向相反

栈满判断

两个栈的栈顶指针相邻时,共享空间用尽:

c
bool IsFull(SharedStack *s) {
    return s->top1 + 1 == s->top2;
}
状态条件
栈 1 空top1 == -1
栈 2 空top2 == MaxSize
栈满(两栈共同满)top1 + 1 == top2

注意:栈满不等于某一个栈满,而是两个栈的总元素数占满了整个数组。只要另一个栈还有空间让出来,就可以继续入栈。

复杂度分析

操作时间复杂度说明
入栈O(1)直接操作栈顶指针
出栈O(1)直接操作栈顶指针
判空O(1)比较栈顶指针与初始值
判满O(1)比较两个栈顶指针

空间复杂度:O(1),所有操作只需常数级辅助空间。共享栈本身使用 O(MaxSize) 的数组空间,但相比两个独立栈,空间利用率更高。

易错:共享栈的栈满条件是 top1 + 1 == top2(两个栈顶指针相邻),不是某一个栈到达数组中点。这意味着一个栈可以占用超过一半的空间,只要另一个栈还有余量。

考研高频考点

  • ⭐ 栈满条件 top1 + 1 == top2(选择题/填空题高频)
  • ⭐ 栈空条件:栈 1 空 top1 == -1,栈 2 空 top2 == MaxSize(易混淆)
  • ⭐ 共享栈的优点:提高空间利用率,适用于两个栈此消彼长的场景
  • 入栈/出栈时指针的移动方向(栈 1 和栈 2 方向相反)
  • 共享栈 vs 两个独立栈的空间利用率对比(简答题)

相关知识

  • 顺序栈是共享栈的基础——理解单个顺序栈的操作后,共享栈只是把两个栈"背靠背"放在同一个数组里
  • 共享栈体现了顺序存储的空间预分配问题:静态数组大小固定,共享是一种折中方案;如果元素个数完全不可预估,可以考虑链栈
  • 共享栈的栈满判断与循环队列的队满判断都是 408 的高频易错点,建议对比记忆