数据结构1—————栈的概念和运算
一. 目录
文章目录
二. 前言和引入
- 在刚接触c的时候,经常听到一个高大上的名词,栈。当时还是萌新的我很懵,栈是个啥,问老师和学长学姐们,他们告诉我,函数储存在栈内存中,是一种先进后先出的储存结构,一个函数运行完毕后在释放。
- 而先进后出,形象来说,栈好像一个封底的盒子,如果想取出盒子中间位置的物品a,必须将这个物品a上面的物品全部移除,这就是先进后出
三. 栈的概念
1. 定义
栈是一种只允许在一端进行插入和删除的线性表,是一种操作受限的线性表。
2. 相关概念
- 栈顶:允许进行删除和插入的一端称为栈顶
- 栈底:不允许进行删除和插入的一端称为栈底
- 出栈:在栈顶进行删除操作
- 入栈:在栈顶进行插入操作
- 空栈:栈内没有元素
3. 特点
先进后出。
4.栈的ADT定义
ADT 栈(stack)
Data//数据对象和逻辑结构
同线性表。元素具有相同的类型,相邻元素具有前驱和后堆关系。
Operation//基本操作
SeqStack *InitStack ():初始化操作.建立一个空栈S。
int StackEmpty (S)://判断是否为空栈 。
Push (*S,e):入栈。
Pop (*S,*e):出栈并返回 。
GetTop (S,*e):取出栈顶元素
StackLength (S):返回回栈S的元素个数。
。
.....
endADT
5. 栈的存储结构
- 顺序存储结构(数组)
- 链式存储结构(链表)
四. 使用栈的顺序存储结构来实现栈的基本运算
1.结构定义
#define MAXSIZE //栈的最大存储空间
#define TRUE 1
#define FALSE 0
typedef /*据情况而定*/ Elemtype;
typedef struct
{
Elemtype data[MAXSIZE];//栈,类型根据情况而定
int top;//指向栈顶
}SeqStack;
- 说明:使用一个数组作为栈,同时定义一个int型变量指向栈顶的元素(其值等于栈顶的下标)。
- 空栈情况:top = -1
- 満栈情况:top = MAXSIZE
- 入栈:top++,并将值存入数组中
- 出栈:返回栈顶元素,top–
2.栈的初始化
SeqStack *InitStack (){
//申请空间
SeqStack *S;
S=malloc(sizeof(SeqStack));
//栈顶初始化
S->top =-1;
return S;
}
3.入栈
int Push (SeqStack *S,Elemtype e){
if(S->top==MAXSIZE-1)//栈已满,添加失败
return FALSE;
S->top++;
S->data[S->top]= e;
return TRUE;
}
4.出栈
int Pop (SeqStack *S,Elemtype *e){
if(S->top == -1)//空栈,出栈失败
return FALSE;
*e=S->data[S->top];
S->top--;
return TRUE;
}
5.其他
对于栈的其他操作,比如判断是否为空,只取出栈顶元素不销毁,销毁栈,等等。都很简单,我就不一一写出来。只写出最主要的出栈和入栈的操作。其他都是这些的稍微变形
五. 双栈邻接共享空间
1. 简介和引入
- 引入:普通的顺序栈有一个很大的问题,那就是初始栈空间,该定为多少,定多太过浪费,定少又可能不够,为了在一定程度上改进这个问题,就提出了共享栈,这一数据结构。
- 共享栈是什么:共享栈是指多个栈共享一同块空间,来起到节约空间的作用,特别适合需要定义两个栈,而且一个栈增多,一个栈减少,这种情况
- 以双栈为例,左栈栈底为0,右栈栈递为MAXSIZE-1
2.结构体定义
#define MAXSIZE 10
#define TRUE 1
#define FALSE 0
typedef int Elemtype;
typedef struct
{
Elemtype data[MAXSIZE];//栈,类型根据情况而定
int lefttop;//指向左栈栈顶位置
int righttop;//指向右栈站顶位置
}DupsqStack;
- 说明:使用一个数组作为栈,同时定义两个一个int型变量指向左右栈顶的元素(其值等于栈顶的下标)。
- 空栈情况:左栈为空lefttop = -1,右栈为空righttop=MAXSIZE-1
- 満栈情况: S->lefttop+1 == S->righttop
3.初始化
DupsqStack *InitDupStack(){
DupsqStack *S;
S=(DupsqStack*)malloc(sizeof(DupsqStack*));
S->lefttop=-1;
S->righttop=MAXSIZE;
return S;
}
4.入栈
int PushDupStack(DupsqStack *S ,char status ,Elemtype x){
if(S->lefttop+1 == S->righttop)
return FALSE;//栈满
if(status == 'L')
S->data[++S->lefttop] =x;
else if(status == 'R')
S->data[--S->righttop] =x;
else
return FALSE;
return TRUE;
}
5.出栈
int PopDupStack(DupsqStack *s ,char status,Elemtype *x){
if(status =='L')
{
if(s->lefttop==-1)//空栈
return FALSE;
*x=s->data[s->lefttop--];
return TRUE;
}
else if(status == 'R')
{
if(s->righttop==MAXSIZE)//空栈
return FALSE;
*x=(s->data[s->righttop++]);
return TRUE;
}
else
return FALSE;//标志符有错
}
六. 链栈
1.简介和引入
- 引入:虽然共享栈在一定情况下,避免了顺序栈带来的空间的浪费,但依然也会出现满栈的情形,所以仿照链表,提出了链栈。
- 链栈:同链表一样,使用指针将一个个节点链接起来,不过不同于链表,链栈只能操作头节点后的节点(栈顶)
- 链栈的栈底是链表的尾部,栈顶是头部后的第一个节点
2.结构体定义
#define TRUE 1
#define FALSE 0
typedef int Elemtype ;
typedef struct Stacknode{
Elemtype date;//数据域
struct Stacknode *next;//指针域
}slStacktype;
- 空栈情况:top->==NULL
- 満栈情况:只有maccol还可以申请到空间,就不会出现満栈的情况
3.初始化
slStacktype *InitDupStack(){
slStacktype *Top;
Top = (slStacktype *)malloc(sizeof(slStacktype));
Top->next = NULL;
return Top;
}
4.入栈
int pushLstack(slStacktype *Top,Elemtype X){
struct Stacknode *New;
if((New = (slStacktype *)malloc(sizeof(slStacktype)))==NULL)
return FALSE;
New->date=X;
//链表的插入操作
New->next=Top->next;
Top->next=New;
return TRUE;
}
5.出栈
//出栈
int PopLstack(slStacktype *Top,Elemtype &X){
if(Top->next==NULL)
return FALSE;
struct Stacknode *pt=Top->next;
*X=pt->date;
//链表的删除操作
Top->next= pt->next;
free(pt);
return TRUE;
}
6.其他
如果存在多个链栈,可将所有的链栈的栈顶Top存入数组中
七. 源码地址
八.参考资料
《大话数据结构》
《数据结构与算法》