前面已经介绍了“链表”,包括顺序链表和链式链表。链表和栈都属于线性表,只是栈是一种特殊的线性表,其“只能够从一端(栈顶)进出”,必须遵循“先进后出”的原则。下面,我们简要学习一下顺序栈和链式栈。
(1)顺序栈
与顺序存储的链表一样,顺序栈也是采用“数组”来存储。其数据结构如下:
[cpp] view plain copy
- #define MAXSIZE 20
- typedef int Elemtype;
- typedef struct
- {
- Elemtype data[MAXSIZE];
- int top;
- }sqStack;
这里我们看出,栈和链表的数据结构几乎一模一样,只是里面的成员含义不同而已。在顺序链表里面,定义的是一个长度length,表示所能够存储的最大数据的个数,这个值是不能变化的;而顺序栈中定义的是栈顶元素的下标,这个值可以变化。

对于栈的操作来说,最重要的是“入栈”和“出栈”。这两个操作都必须遵循“FILO”的原则,其具体实现如下:
[cpp] view plain copy
- //入栈
- bool Push(sqStack *S, Elemtype e)
- {
- if(S->top >= MAXSIZE - 1)
- return false;
- S->top++; //要细心,不能单独用top,而是引用结构体中的元素
- S->data[s->top] = e;
- return true;
- }
- //出栈
- bool Pop(sqStack *S, Elemtype *e)
- {
- if(S->top == 0)
- return false;
- *e = S->data[S->top];
- S->top--;
- return true;
- }
从上面的知识中,可以知道,顺序栈的操作很方便,但其最大的不足在于,必须事先确定数据存储的最大空间。这里,我们扩展一下知识,下面介绍一下如何做到两个顺序栈共享数据空间。这个方法的基本思想为:数组空间有两个端点,两个栈有两个栈底;让一个栈的栈底位于数组的起始端(下标为0处),让另一个栈的栈底位于数组的末端(下标为N-1处);如果要向栈里面添加元素,那么使栈顶向数组中间移动即可。
数据结构如下:
[cpp] view plain copy
- typedef struct
- {
- Elemtype data[MAXSIZE];
- int top1;
- int top2;
- }sqDoubleStack;
入栈操作:
[cpp] view plain copy
- bool Push(sqDoubleStack *S, Elemtype e, int stackNumber)
- {
- if(S->top1+1 == S->top2)//特别注意,如果栈满了,top1和top2不是相等的,而是两者前后相邻,因此要加1
- return false;
- if(stackNumber == 1)
- {
- S->top1++;
- S->data[S->top1] = e;
- return true;
- }
- if(stackNumber == 2)
- {
- S->top2++;
- S->data[S->top2] = e;
- return true;
- }
- }
(2)链式栈
链式存储的栈就不会存在“栈满”的现象。因此,在进行入栈、出栈的时候,就不用再判断是否满栈了。在对链式栈进行操作时,始终要把握一点:首先看到的是整个栈,而不每一个结点;对于整个栈,只有两个指标——栈顶指针(top)和栈元素个数(count);这样,我们就能够通过栈顶指针(top)来取到栈顶的一个结点,从而获取其中的数据data,并可以创建指针,移动指针位置,遍历栈中的各个元素。也就是说,我们必须“从栈(top、count),再到结点(data、next)”。
其数据解结构可以定义为:
[cpp] view plain copy
- typedef struct StackNode
- {
- Elemtype data;
- struct StackNode * next;
- }StackNode, *LinkStackPtr;
- typedef struct LinkStack
- {
- LinkStackPtr top;//这里top是一个stack结点类型的指针,指向Stack结点(栈顶)
- int count;
- }LinkStack;
入栈操作:
[cpp] view plain copy
- bool Push(LinkStack *S, Elemtype e)
- {
- LinkStackPtr tmp = (LinkStackPtr)malloc(sizeof(StackNode));
- tmp->data = e;
- tmp->next = S->top;
- S->top = tmp;
- S->count++;
- return true;
- }
出栈操作:
[cpp] view plain copy
- bool Pop(LinkStack *S, Elemtype *e)
- {
- LinkStack p;
- *e = S->top->data;
- p = S->top;
- S->top = S->top->next;
- free(p);
- S->count--:
- return true;
- }