从数据结构角度看,栈和队列都是线性表,其特殊性在于基本操作是线性表的子集。栈和队列都是操作受限的线性表(比如不能从中间插入和删除),因此可称为限定性的数据结构。
从数据类型角度看,栈和队列是和线性表大不同的两类重要的抽象数据类型
定义:
- 栈:限定仅在表尾进行插入或删除操作的线性表。
- 栈顶:表尾
- 栈底:表头
- 空栈:空表
栈的修改是按照后进先出的原则进行的,因此,栈又称为后进先出的线性表。
栈的实现:
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#define OVERFLOW -2
#define OK 1
#define ERROR 0
#define TRUE 1
#define FLASE 0
//--------------栈的顺序存储表示-----------------
#define STACK_INIT_SIZE 100 // 存储空间初始分配量
#define STACKINCREMENT 10 //存储空间分配增量
typedef int SElemType;
typedef int Status;
typedef struct {
SElemType *base; // 在栈构造之前和销毁之后,base的值为NULL
SElemType *top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
}SqStack;
// --------------基本操作的函数原型说明-----------------
Status InitStack(SqStack &S) {
// 构造一个空栈S
S.base = (SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
if (!S.base) exit(OVERFLOW);
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return OK;
}
Status DestoryStack(SqStack &S) {
// 销毁栈S,S不再存在
free(S.base);
S.base = NULL;
S.top = NULL;
S.stacksize = 0;
return OK;
}
Status ClearStack(SqStack &S) {
// 把S置为空栈
S.top = S.base; // S.top指向栈底之后,再插入就从栈底插,等价于清空
return OK;
}
Status StackEmpty(SqStack S) {
// 若栈S为空栈,则返回TRUE, 否则返回FLASE
if (S.top == S.base) return TRUE;
return FLASE;
}
int StackLenght(SqStack S) {
// 返回S的元素个数,即栈的长度
return S.top - S.base;
}
Status GetTop(SqStack S, SElemType &e) {
// 若栈不空,则用e返回S的栈顶元素,并返回OK,否则返回ERROR
if (S.top == S.base) return ERROR; // 如果S.top == S.base,则说明栈S为空栈
e = *(S.top - 1);
return OK;
}
Status Push(SqStack &S, SElemType e) {
// 插入元素e为新的栈顶元素
if (S.top - S.base >= S.stacksize) { // 栈满,追加存储空间
S.base = (SElemType *)realloc(S.base, (S.stacksize + STACKINCREMENT) * sizeof(SElemType));
if (!S.base)exit(OVERFLOW); // 存储分配失败
S.top = S.base + S.stacksize; // S.top重新指向栈顶
S.stacksize += STACKINCREMENT;
}
*S.top++ = e; // 先把e值插入到栈顶,然后S.top自增一位指向栈顶元素后一位
return OK;
}
Status Pop(SqStack &S, SElemType &e) {
// 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
if (S.top == S.base) return ERROR; // 如果S.top == S.base,则说明栈S为空栈
e = *--S.top; // S.top的值先自减,指向栈顶元素,再插入时是从该位置插入,也就相当于删除
return OK;
}
Status StackTraverse(SqStack S, Status(* visit)(SElemType)) {
// 从栈底到栈顶一次对栈中每个元素调用函数visit()。一旦visit()失败,则操作失败
int * cur = S.base;
while (S.top > S.base) {
visit(*S.base++);
}
S.base = cur;
return OK;
}
Status visit(SElemType e) {
printf("%d", e);
return OK;
}
栈的应用:
void conversion() {
// 对于输入的任意一个非负十进制整数,打印输出与其等值的八进制数
SqStack S;
int N, e;
InitStack(S); // 构造空栈
scanf_s("%d", &N);
while (N) {
Push(S, N % 8); // 取N整除8的余数
N = N / 8; // 取N整除8的值
}
while (!StackEmpty(S)) {
Pop(S, e);
printf("%d", e);
}
}
int expectance() {
// 用“期待的急迫程度”这个概念来描述检验括号是否匹配的方法
char brackets[] = "[([][])]";
int e;
SqStack S;
InitStack(S);
for (int i = 0; i < 8; i++) {
printf("当前处理字符:%c\n", brackets[i]);
printf("当前栈长度:%d\n", StackLenght(S));
if (brackets[i] == '[' || brackets[i] == '(') {
Push(S, brackets[i]);
continue;
}
if (StackEmpty(S)) return ERROR;
if ((GetTop(S, e) == '[' && brackets[i] == ')') || (GetTop(S, e) == '(' && brackets[i] == ']')) return ERROR;
Pop(S, e);
}
printf("结束时栈长度:%d\n", StackLenght(S));
return OK;
}
------------------摘自《数据结构》严蔚敏.吴伟良版