栈
- 限定仅在表尾进行插入和删除操作的线性表
- 对于某个出栈的元素,在它之前进栈却晚出栈的元素必定按逆序出栈
- LIFO
ADT
ADT 栈(stack)
Data
同线性表。元素具有相同的类型,相邻元素具有前驱和后堆关系。
Operation
InitStack ( *S ):初始化操作.建立一个空栈S。
DestroyStack ( *S ):若栈存在,則销毁它。
ClearStack (*S):将栈清空。
StackEmpty ( S ):若栈为空,返回true,否則返回 false。
GetTop (S,*e):若栈存在且非空,用e返回S的栈顶元素。
Push (*S,e):若栈S存在,插入新元素e到栈S中并成为栈頂元素。
Pop (*S,*e):删除栈S中栈顶元素,并用e返回其值。
StackLength (S):返回回栈S的元素个数。
endADT
顺序栈
- top变量表示栈顶元素在数组中的位置
- 栈有一个元素: top == 0
- 空栈: top == -1
- 满栈: top == MAXSIZE - 1
存储结构
typedef int SElemType
typedef struct
{
SElemType data[MAXSIZE];
int top;
}SqStack;
Push
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status;
Status Push(SqStack *s, SElemType e)
{
if(S->top == MAXSIZE - 1)
{
return ERROR;
}
S->top++;
S->data[S->top]=e;
return OK;
}
POP
Status Pop(SqStack *S, SElemType *e)
{
if(S->top == 1){
return ERROR;
}
*e = S->data[S->top];
S->top--;
return OK;
}
共享栈
- 从数组两端向中间靠拢
- 栈1空:top1 == -1
- 栈2空:top2 == n
- 栈满:top1 + 1 == top2
- 应用背景:两个栈空间需求有相反关系 且 数据类型要相同
存储结构
typedef struct{
SElemType data[MAXSIZE];
int top1;
int top2;
}SqDoubleStack;
Push
Status Push(SqDoubleStack *s, SElemType e, int stackNumber){
if(S->top1+1 == S->top2){
return ERROR;
}
if(stackNumber == 1){
S->data[++S->top1]=e;
}else if(stackNumber == 2){
S->data[--S->top2]=e;
}
return OK;
Pop
Status Pop(SqDoubleStack *S, SElemType *e, int stackNumber){
if(stackNumber == 1){
if(S->top1 == -1){
return ERROR;
}
*e=S->data[S->top1--];
}
else if(stackNumber == 2){
if(S->top2 == MAXSIZE){
return ERROR;
}
*e=S->data[S->top2++];
}
return OK;
}
链栈
- 不带头结点的单链表
- 栈顶在头部
- 内存够用则不存在栈满的情况
- 空栈:top == NULL
- 内存开销大,如果栈大小变化显著,用链栈,否则用顺序栈
存储结构
teypedef struct StackNode
{
SElemType data;
struct StackNode *next;
} StackNode, *LinkStackPtr;
teypedef struct LinkStack
{
LinkStackPrt top;
int count;
}LinkStack;
Push
Status Push(LinkStack *S, SElemType e)
{
LinkStackPtr s = (LinkStackPtr) malloc (sizeof(StackNode));
s->data = e;
s->next = S->top;
S->top = s;
S->count++;
return OK;
}
Pop
Status Pop(LinkStack *S, SElemType *e)
{
LinkStackPtr p;
if( StackEmpty(*S) )
return ERROR;
*e = S->top->data;
p = S->top;
S->top = S->top->next;
free(p);
S->count--;
return OK;
}
栈的应用
递归
斐波那契数列
int Fbi(int i){
if( i<2 )
return i == 0 ? 0 : 1;
return Fbi(i-1)+Fbi(i-2);
}
int main(){
int i;
fot( int i=0; i<40; i++){
print("%d ", Fbi(i));
}
return 0;
}
四则运算表达式求值
逆波兰计算器
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#define STACK_INIT_SIZE 20
#define STACKINCREMENT 10
#define MAXBUFFER 10
typedef double ElemType;
typedef struct
{
ElemType *base;
ElemType *top;
int stackSize;
}sqStack;
void InitStack(sqStack *s)
{
s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
if( !s->base )
exit(0);
s->top = s->base;
s->stackSize = STACK_INIT_SIZE;
}
void Push(sqStack *s, ElemType e)
{
if( s->top - s->base >= s->stackSize )
{
s->base = (ElemType *)realloc(s->base, (s->stackSize + STACKINCREMENT) * sizeof(ElemType));
if( !s->base )
exit(0);
s->top = s->base + s->stackSize;
s->stackSize = s->stackSize + STACKINCREMENT;
}
*(s->top) = e;
s->top++;
}
void Pop(sqStack *s, ElemType *e)
{
if( s->top == s->base )
return;
*e = *--(s->top);
}
int StackLen(sqStack s)
{
return (s.top - s.base);
}
int main()
{
sqStack s;
char c;
double d, e;
char str[MAXBUFFER];
int i = 0;
InitStack( &s );
printf("请按逆波兰表达式输入待计算数据,数据与运算符之间用空格隔开,以#作为结束标志: \n");
scanf("%c", &c);
while( c != '#' )
{
while( isdigit(c) || c=='.' )
{
str[i++] = c;
str[i] = '\0';
if( i >= 10 )
{
printf("出错:输入的单个数据过大!\n");
return -1;
}
scanf("%c", &c);
if( c == ' ' )
{
d = atof(str);
Push(&s, d);
i = 0;
break;
}
}
switch( c )
{
case '+':
Pop(&s, &e);
Pop(&s, &d);
Push(&s, d+e);
break;
case '-':
Pop(&s, &e);
Pop(&s, &d);
Push(&s, d-e);
break;
case '*':
Pop(&s, &e);
Pop(&s, &d);
Push(&s, d*e);
break;
case '/':
Pop(&s, &e);
Pop(&s, &d);
if( e != 0 )
{
Push(&s, d/e);
}
else
{
printf("\n出错:除数为零!\n");
return -1;
}
break;
}
scanf("%c", &c);
}
Pop(&s, &d);
printf("\n最终的计算结果为:%f\n", d);
return 0;
}
中缀转后缀(逆波兰)表示法
#include <stdio.h>
#include <stdlib.h>
#define STACK_INIT_SIZE 20
#define STACKINCREMENT 10
typedef char ElemType;
typedef struct
{
ElemType *base;
ElemType *top;
int stackSize;
}sqStack;
void InitStack(sqStack *s)
{
s->base = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
if( !s->base )
exit(0);
s->top = s->base;
s->stackSize = STACK_INIT_SIZE;
}
void Push(sqStack *s, ElemType e)
{
if( s->top - s->base >= s->stackSize )
{
s->base = (ElemType *)realloc(s->base, (s->stackSize + STACKINCREMENT) * sizeof(ElemType));
if( !s->base )
exit(0);
s->top = s->base + s->stackSize;
s->stackSize = s->stackSize + STACKINCREMENT;
}
*(s->top) = e;
s->top++;
}
void Pop(sqStack *s, ElemType *e)
{
if( s->top == s->base )
return;
*e = *--(s->top);
}
int StackLen(sqStack s)
{
return (s.top - s.base);
}
int main()
{
sqStack s;
char c, e;
InitStack( &s );
printf("请输入中缀表达式,以#作为结束标志:");
scanf("%c", &c);
while( c != '#' )
{
while( c>='0' && c<='9' )
{
printf("%c", c);
scanf("%c", &c);
if( c<'0' || c>'9' )
{
printf(" ");
}
}
if( ')' == c )
{
Pop(&s, &e);
while( '(' != e )
{
printf("%c ", e);
Pop(&s, &e);
}
}
else if( '+'==c || '-'==c )
{
if( !StackLen(s) )
{
Push(&s, c);
}
else
{
do
{
Pop(&s, &e);
if( '(' == e )
{
Push(&s, e);
}
else
{
printf("%c ", e);
}
}while( StackLen(s) && '('!=e );
Push(&s, c);
}
}
else if( '*'==c || '/'==c || '('==c )
{
Push(&s, c);
}
else if( '#'== c )
{
break;
}
else
{
printf("\n出错:输入格式错误!\n");
return -1;
}
scanf("%c", &c);
}
while( StackLen(s) )
{
Pop(&s, &e);
printf("%c ", e);
}
return 0;
}