栈的概念
- 栈(Stack):是限制在表的一端进行插入和删除操作的线性表。又称为后进先出LIFO(Last In First Out)或先进后出FILO(First In Last Out)线性表。
- 栈顶(Top):允许进行插入、删除操作的一端,又称为表尾。用栈顶指针(top)来指示栈顶元素。
- 栈底(Bottom):是固定端,又称为表头。
- 空栈:当表中没有元素时称为空栈。
栈的抽象数据类型
ADT Stack{
数据对象:(D={a_i|a_i∈ElemSet,i=1,...,n,n≥0})
数据关系:(R={<a_{i-1},a_i>|a_{i-1},a_i∈D,i=2,3,...n})
基本操作:初始化、进栈、出栈、取栈顶元素等
}ADT Stack
栈的顺序存储表示
栈的顺序存储结构简称为顺序栈,和线性表相类似,用一维数组来存储栈。根据数组是否可以根据需要增大,又可以分为静态顺序栈和动态顺序栈。
静态顺序栈:实现简单,但不能根据需要增大栈的存储空间;
动态顺序栈:可以根据需要增大栈的存储空间,但是实现稍为复杂。
栈的动态顺序存储表示
采用动态一维数组来存储栈,栈的大小可以根据需要增加。
栈底(bottom)固定不变,栈顶(top)随着进栈和退栈操作而变化;
top=bottom作为栈空的标记,每次top指向栈顶数组中的下一个存储位置;
结点进栈:首先将数据元素保存到栈顶(top所指的当前位置),然后执行top加1,使top指向栈顶的下一个存储位置;
结点出栈:首先执行top减1,使top指向栈顶元素的存储位置,然后将栈顶元素取出。
- 栈的类型定义
#define STACK_SIZE 100 /* 栈初始向量大小*/
#define STACKINCREMENT 10 /* 存储空间分配增量*/
#typedef int ElemType;
typedef struct sqstack
{ ElemType *bottom; /* 栈不存在时值为NULL*/
ElemType *top; /*栈顶指针*/
int stacksize; /*当前已分配空间,以元素为单位*/
}SqStack;
- 栈的初始化
Status Init_Stack(void)
{ SqStack S;
S.bottom = (ElemType*)malloc(STACK_SIZE*sizeof(ElemType));
if(!S.bottom) return ERROR;
S.top = S.bottom ; /*栈空时栈顶和栈底指针相同*/
S.stacksize = STACK_SIZE;
return OK;
}
- 元素进栈
Status Push(SaStack S,ElemType e)
{ if(S.top-S.bottom>=S.stacksize-1)
{ S.bottom = (ElemType*)realloc((S.STACKINCREMENT+STACK_SIZE)*sizeof(ElemType));
/*栈满,追加存储空间*/
if(!S.bottom) return ERROR;
S.top = S.bottom + S.stacksize;
S.stacksize += STACKINCREMENT;
}
*S.top = e;S.top++;/*栈顶指针加1,e成为新的栈顶*/
return OK;
}
- 元素出栈
Status pop(SaStack S,ElemType *e)
/*弹出栈顶元素*/
{ if(S.top==S.bottom)
return ERROR; /*栈空,返回失败标志*/
S.top--;e = S.top;
return OK;
}
栈的静态顺序存储表示
采用静态一维数组来存储栈,栈底固定不变,栈顶随着进栈和退栈操作变化。
栈底(bottom)固定不变,栈顶(top)随着进栈和退栈操作而变化;
top=0作为栈空的标记,每次top指向栈顶在数组中的存储位置;
结点进栈:首先执行top加1,使top指向新的栈顶位置,然后将数据元素保存到栈顶(top所指的当前位置);
结点出栈:首先把top指向的栈顶元素取出,然后执行top减1,使top指向新的栈顶位置。
若栈的数组有Maxsize个元素,则top=Maxsize-1时栈满。
- 栈的类型定义
#define MAX_STACK_SIZE 100 /* 栈向量大小*/
#typedef int ElemType;
typedef struct sqstack
{ ElemType stack_array[MAX_STACK_SIZE ];
int top;
}SqStack;
- 栈的初始化
SqStack Init_Stack(void)
{ SqStack S;
S.bottom = S.top = 0;
return(S);
}
- 元素进栈
Status Push(SaStack S,ElemType e)
/*使数据元素e进栈成为新的栈顶*/
{ if(S.top==MAX_STACK_SIZE -1)
return ERROR; /*栈满,返回错误标志*/
S.top++; /*栈顶指针加1*/
S.stack_array[S.top]=e;/*e成为新的栈顶*/
return OK; /*进栈成功*/
}
}
- 元素出栈
Status pop(SaStack S,ElemType *e)
/*弹出栈顶元素*/
{ if(S.top==0)
return ERROR; /*栈空,返回失败标志*/
*e = stack_array[S.top];
S.top--;
return OK;
}
栈的链式存储表示
栈的链式表示
栈的链式存储结构称为链栈,是运算受限的单链表。其插入和删除操作只能在表头位置上进行。因此,链栈没有必要像单链表那样附加头结点,栈顶指针top就是链表的头指针。
- 链栈的类型定义
typedef struct Stack_Node
{ ElemType data;
struct Stack_Node *next;
}Stack_Node;
- 栈的初始化
Stack_Node *Init_Link_Stack(void)
{ Stack_Node *top;
top=(Stack_Node *)malloc(sizeof(Stack_Node));
top->next=null;
return(top);
}
- 元素进栈
Status Push(Stack_Node *top,ElemType e)
/*使数据元素e进栈成为新的栈顶*/
{ Stack_Node *p;
p=(Stack_Node *)malloc(sizeof(Stack_Node));
if(!p) return ERROR;
/*申请新结点失败,返回错误标志*/
p->data=e;
p->next=top->next;
top->next=p; /*钩链*/
return OK;
}
- 元素出栈
Status pop(Stack_Node *top,ElemType *e)
/*弹出栈顶元素*/
{ Stack_Node *p;
ElemType e;
if(top->next==NULL)
return ERROR; /*栈空,返回失败标志*/
p=top->next;
e=p->data; /*取栈顶元素*/
top->next=p->next;/*修改栈顶指针*/
free(p);
return OK;
}