2018.9.27
“enmmm,今天写的第一篇博客想讲讲数据结构中的栈.”
栈(Stack)是限定仅在表尾进行插入或删除操作的线性表.因此,对栈来说,表尾端称为栈顶(top),表头端称为栈底(bottom).栈的修改是按照后进先出(LIFO:last in first out)的原则.
栈的抽象数据类型的定义:
ADT Statck{
数据对象:D={ai|ai∈ElemSet,i-1,2,...,n, n>=0}
数据关系:R1={<ai-1,ai>|ai-1,ai∈D,i=2,...,n} 约定ai为栈顶,ai-1为栈底.
基本操作:InitStack(&S)
DestroyStack(&S)
ClearStack(&S)
StackEmpty(S)
StackLength(S)
GetTop(S,&e)
Push(&S,e)
Pop(&S,&e)
StackTraverse(S,visit())
}ADT Stack
①顺序栈,即栈的顺序存储结构是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置.
typedef struct{
SElemType *base;//base是栈底指针,始终指向栈底的位置
SElemType *top;//top为栈顶指针,其初值指向栈底
int stacksize;//stacksize指示栈的当前可用的最大容量
}SqStack;
若base的值为NULL,则表明栈结构不存在;若top=base,则为空栈;每当插入新的栈顶元素时,指针top增1,删除栈顶元素时,top减1,因此,非空栈的栈顶指针始终在栈顶元素的下一个位置上.
以下是顺序栈的模块说明:
#define STACK_INIT_SIZE 100;//存储空间初始分量
#define STACKINCREMENT 10;//存储空间分配增量
typedef struct{
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
Status InitStack(SqStack &S);
Status GetTop(SqStack S,SElemType &e);
Status Push(SqStack &S,SElemType e);
Status Pop(SqStack &S,SElemType &e);
Status StackLength(SqStack S);
Status StackEmpty(SqStack S);
/*基本操作的算法描述*/
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;
}//InitStack
Status GetTop(SqStack S,SElemType &e){
if(S.top==S.base) return ERROR;
e=*(S.top-1);
return OK;
}//GetTop
Status Push(SqStack &S,SElemType e){
//先判断是否栈满
if(S.top-S.base>=S.stacksize){
newbase=(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;//*S.top=e,S.top++
return OK;
}Push
Status Pop(SqStack &S,SElemType &e){
if(S.top==S.base) return ERROR;
e=--*S.top;//--S.top,*S.top=e
return OK;
}//Pop
Status StackLength(SqStack S){
return (S.top-S.base);
}//StackLength
Status StackEmpty(SqStack S){
return (S.base==S.top);
}//StackEmpty,两指针重合,则为空栈
Q1:两个指针如何共享一片连续的存储空间?
A1:“底设两段,相向而动,迎面增长”–>S1.base██ ██ ██–>S2.base
Q2:设入栈序列为1 2 3 4,那么可能得到的出栈序列是什么?有多少种?
A2:可能得到的出栈序列(4个元素一共有 A44 共24种排列):
1 2 3 4 √
1 2 4 3 √
1 3 2 4 √
1 3 4 2 √
1 4 2 3 ×
1 4 3 2 √
2 1 3 4 √
2 1 4 3 √
2 3 1 4 √
2 3 4 1 √
2 4 1 3 ×
2 4 3 1 √
3 1 2 4 ×
3 1 4 2 ×
3 2 1 4 √
3 2 4 1 √
3 4 1 2 ×
3 4 2 1 √
4 1 2 3 ×
4 1 3 2 ×
4 2 1 3 ×
4 2 3 1 ×
4 3 2 1 √
4 3 1 2 ×
以上合法排序共计14个.
栈的应用举例之数制转换(使用位权展开法)
void conversion()
{
InitStack(S);
cin>>N;
while(N){
Push(S,N%r);
N=N/r;
}
while(!StackEmpty(S)){
Pop(S,e);
if(e>=0 && e<=9)
cout<<e;
else
cout<<"e-10+'A'";
}
}//conversion
设计算法时要考虑到算法的通用性