栈的认识和理解
栈(stack)
栈是一种只能在一端进行插入或删除操作的线性表。
栈只能选取同一个端点进行插入和删除操作
栈的主要特点是“后进先出(LIFO)”,即后进栈的元素先出栈。栈也称为后进先出表。
1.栈的几个基本概念
- 允许进行插入、删除操作的一端称为栈顶。
- 表的另一端称为栈底。
- 当栈中没有数据元素时,称为空栈。
- 栈的插入操作通常称为进栈或入栈。
- 栈的删除操作通常称为退栈或出栈。
2.栈的几个基本操作 - InitStack(&s):初始化栈。构造一个空栈S。
- DestroyStack(&s):销毁栈。释放栈s占用的存储空间。
- StackEmpty(s):判断栈是否为空:若栈s为空,则返回真;否则返回假
- Push(&S,e):进栈。将元素e插入到栈s中作为栈顶元素。
- Pop(&s,&e):出栈。从栈s中退出栈顶元素,并将其值赋给e。
- GetTop(s,&e):取栈顶元素。返回当前的栈顶元素,并将其值赋给e。
——————————————————我是分割线—————————————————————
栈中元素逻辑关系与线性表的相同,栈可以采用与线性表相同的存储结构。
一、栈的顺序存储结构(顺序栈)及基本运算的实现
1.定义顺序栈
假设一个顺序栈的数据类型全部为ElemType,而且这个栈的元素个数最大不超过MaxSize,那么可以这样来定义这个顺序栈。
typedef struct{
ElemType data[MaxSize];
int top; //栈顶指针
} SqStack;
假设这个栈的MaxSize=5
该栈现在为一个空栈,栈中没有任何元素,所以栈顶指针top指向的位置就在-1的位置
而后又分别进行了将一个元素压入栈中,将栈堆满,出栈一次的操作。RT
顺序栈4要素
- 栈空条件:top=-1
- 栈满条件:top=MaxSize-1
- 进栈e操作:top++; 将e放在top处
- 退栈操作:从top处取出元素e; top–;
2.初始化栈InitStack(&s)
新建一个栈实际上就是将栈顶指针top指向-1
void InitStack(SqStack *&s){
s=(SqStack *)malloc(sizeof(SqStack));
s->top=- 1 ;
}
s为栈指针,top为s所指栈的栈顶指针
3.销毁栈DestroyStack(&s)
释放s占用的储存空间,c语言里有对应点free函数,调用释放即可。
void DestroyStack(SqStack *&s){
free(S);
}
4.判断栈是否为空StackEmpty(s)
想要判断栈是否为空栈,只需判断top指针是否指向-1即可。
bool StackEmpty(SqStack *s){
return(s->top==- 1);
}
5.进栈Push(&s,e)
在栈不满的条件下,先将栈指针增1,然后在该位置上插入元素e。
bool Push(SqStack *&s,ElemType e){
if (s->top==MaxSize-1) //栈满的情况,即栈上溢出
return false;
s->top++; //栈顶指针增1 s->data[s->top]=e; //元素e放在栈顶指针处
return true;
}
6.出栈Pop(&s,&e)
在栈不为空的条件下,先将栈顶元素赋给e,然后将栈指针减1。
bool Pop(SqStack *&s,ElemType &e){
if (s->top==-1) //栈为空的情况,即栈下溢出
return false;
e=s->data[s->top]; //取栈顶指针元素的元素
s->top--; //栈顶指针减1
return true;
}
7.取栈顶元素GetTop(s,&e)
在栈不为空的条件下,将栈顶元素赋给e。
bool GetTop(SqStack *s,ElemType &e){
if (s->top==-1) //栈为空的情况,即栈下溢出
return false;
e=s->data[s->top]; //取栈顶指针元素的元素
return true;
}
二、栈的链式存储结构及其基本运算的实现
链栈和顺序栈的关系就像是顺序表中链表和数组的关系。
采用链表存储的栈称为链栈,这里采用带头节点的单链表实现。
链栈的4要素:
- 栈空条件:s->next=NULL
- 栈满条件:不考虑 //由于链栈是链式存储结构所以不考虑栈满的情况,这也是链栈和顺序栈的一个区别
- 进栈e操作:将包含e的节点插入到头节点之后
- 退栈操作:取出头节点之后节点的元素并删除
链栈的基本运算实现和顺序栈十分接近
//1.链栈的定义
typedef struct linknode{
ElemType data; //数据域
struct linknode *next; //指针域
} LiStack;
//2.初始化栈initStack(&s)
void (LiStack *&s){
s=(LiStack *)malloc(sizeof(LiStack));
s->next=NULL;
}
//3.销毁栈DestroyStack(&s)
void DestroyStack(LiStack *&s){
LiStack *p=s,*q=s->next;
while (q!=NULL)
{ free(p);
p=q;
q=p->next;
}
free(p); //此时p指向尾节点,释放其空间
}
//4.判断栈是否为空StackEmpty(s)
bool StackEmpty(LiStack *s)
{
return(s->next==NULL);
}
//6.进栈Push(&s,e)
void Push(LiStack *&s,ElemType e)
{ LiStack *p;
p=(LiStack *)malloc(sizeof(LiStack));
p->data=e; //新建元素e对应的节点p p->next=s->next; //插入p节点作为开始节点
s->next=p;
}
//7.出栈Pop(&s,&e)
bool Pop(LiStack *&s,ElemType &e)
{ LiStack *p;
if (s->next==NULL) //栈空的情况
return false;
p=s->next; //p指向开始节点
e=p->data;
s->next=p->next; //删除*p节点
free(p); //释放*p节点
return true;
}
以上为数据结构堆栈的一些认识。
参考资料:
- 武汉大学李春葆教授数据结构课件
- 百度百科
以上有错欢迎指正,希望让更多人看到。都看到这了点个赞再走呗☺