栈
操作受限的线性表,即限定性的数据结构
定义
栈(stack)是限定仅在表尾进行插入或删除操作的线性表。
栈顶(top)是表尾端。
栈底(bottom)是表头端。
基本操作:
ADT Stack {
数据对象:
数据关系:
基本操作:
InitStack(&s);
ClearStack(&s);
StackEmpty(s);
StackLength(s);
GetTop(s, &e);
Push(&s, e);
Pop(&s, &e);
StackTraverse(s, visit());
}ADT Stack
栈的表示和实现
顺序栈
typedef struct {
SElemType *base;
SEleType *top;
int stacksize;
}SqStack;
实现
#define STACK_INIT_SIZE 100;
#define STACKINCREMENT 10;
typedef struct {
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
/* 函数定义 */
Status InitStack(SqStack &s);
Status DestroyStack(SqStack &s);
Status ClearStack(SqStack &s);
Status StackEmpty(SqStack s);
int StackLength(SqStack s);
Status GetTop(SqStack s, SElemType &e);
Status Push(SqStack &s, SElemType e);
Status Pop(SqStack &s, SElemType &e);
// 从栈底到栈顶一次对栈中每个元素调用函数visit().一旦visit()失败,则操作失败
Status StackTraverse(SqStack s, Status (*visit)());
/* 函数部分实现 */
Status InitStack(SqStack &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 GetTop(SqStack s, SElemType &e) {
if(s.top == s.base) return ERROR;
e = *(s.top - 1);
return OK;
}
Status Push(SqStack &s, SElemType 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.stacksize += STACKINCREMENT;
}
*s.top++ = e;
return OK;
}
Status Pop(SqStack &s, SElemType &e) {
if(s.top == s.base) return ERROR;
e = * --s.top;
return ok;
}
应用
数制转换
// 1348 转成8进制 2504
void conversion() {
InitStack(s);
scanf("%d", N);
while(N) {
Push(s, N%8);
N = N/8;
}
while(!StackEmpty(s)) {
Pop(s, e);
printf("%d", e);
}
}
括号匹配的校验
行编辑程序
迷宫求解
穷举求解
do {
若当前位置可通,
则 { 将当前位置插入栈顶;
若该位置是出口位置,则结束;
否则切换当前位置的东邻方块为新的当前位置;
}
否则,
若栈不空且栈顶位置尚有其他方向未经探索,
则设定新的当前位置为沿顺时针方向旋转找到的栈顶位置的下一相邻块;
若栈不空但栈顶位置的四周均不可通,
则 { 删去栈顶位置;
若栈不空,则重新测试新的栈顶位置,
直至找到一个可通的相邻块或出栈至栈空;
}
} while(栈不空);
// 结构
typedef struct {
int ord; // 通道块在路径上的序号
PosType seat; // 通道快在迷宫中的坐标位置
int di; // 从此通道块走向下一通道块的方向
}SElemType;
Status MazePath(MazeType maze, PosType start, PostType end) {
// 若迷宫maze中存在从入口start到出口end的通道,则求得一条存放在栈中
InitStack(s); curpos = start;
curstep = 1;
do {
if(Pass(curpos)) {
FootPrint(curpos);
e = (curstep, curpos, 1);
Push(s,e);
if(curpos == end) return TRUE;
curpos = NextPos(curpos, 1);
curstep++;
}
else {
if(!StackEmpty(s)) {
Pop(s,e);
while(e.di == 4 && ! StackEmpty(s)) {
MarkPrint(e.seat); Pop(s,e);
}
if(e.di < 4) {
e.di++; Push(s,e);
curpos = NextPos(e.seat, e.di);
}
}
}
}while(!StackEmpty(s);
return FALSE;
}
表达式求值
运算符优先法
OperandType EvaluateExpression() {
// 算术表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和运算数栈
// OP为运算符集合
InitStack(OPTR); Push(OPTR, '#');
initStack(OPND); c = getchar();
while(c!='#' || GetTop(OPTR)!='#') {
if(!In(c, OP) { Push((OPND, c); c = getchar(); }
else
switch(Precede(GetTop(OPTR), c)) {
case '<':
Push(OPTR, c); c = getchar();
break;
case '=':
Pop(OPTR, x); c = getchar();
break;
case '>':
Pop(OPTR, theta);
Pop(OPND, b); Pop(OPND, a);
Push(OPND, Operatr(a, theta, b));
break;
}
}
return GetTop(OPND);
}
栈与递归的实现
栈还有一个重要应用是在程序设计语言中实现递归。
汉诺塔问题
void hanoi(int n, char x, char y, char z)
{
if(n==1)
move(x, 1, z);
else {
hanoi(n-1, x, z, y);
move(x, n, z);
hanoi(n-1, y, x, z);
}
}