第四章:栈与队列
1.栈的定义:
栈后进先出,和弹夹的子弹一样,先进去的子弹后出来,后进去的先出来。栈的应用很多,word,ps,sai的撤销都是用栈这种方法实现的。
栈是限定仅在表尾进行插入和删除操作的线性表。
在定义中的表尾进行操作指的是在栈顶。
把允许插入和删除的一端称为栈顶(top),另一端就是栈底(bottom),不含任何数据元素的栈称为空栈。
栈是一个线性表,也就是说,栈元素具有前驱后继的线性关系,不过它是特殊的线性表。在定义中的表尾进行操作指的是在栈顶。栈的特殊就在这个线性表的插入和删除位置始终在栈顶进行,栈底固定,先进栈的只能在栈底。
栈的插入操作:进栈。类似子弹压入弹夹,只能进一次,出栈了不能回来
栈的删除操作:出栈。类似子弹出弹夹。
2.进栈出栈的变化形式:
最先进栈的元素并不一定最后出栈,因为栈对插入和删除位置进行限制,但没有对元素入栈时间进行限制。所以,在不是所有元素都一起进栈的情况下,先入栈的元素也可以出栈,只要保证是栈顶元素出栈就行。
例如:
有元素1,2,3,有哪些出入栈顺序?
第一种:1,2,3进 3,2,1出(最简单情况)
第二种:1进1出,2进,2出,3进,3出、
第三种:1进2进2出3进3出1出
等等
有没有可能出现312出栈这种情况?
不可能,因为3出栈了,代表1和2一定进栈了,2一定在1的前面出栈,所以321可以312不行,不然不满足1,2,3依次进栈的要求。
3 栈的抽象数据类型
ADT 栈(stack)
Data
同线性表,元素具有相同类型,相邻元素具有前驱和后继关系
Operation
InitStack(*s) :初始化操作,建立一个空栈s
DestroyStack(*s) :若栈存在,销毁它
ClearStack(*s) :讲栈清空
StackEmpty(s) :若栈为空,返回true,否则返回false
GetTop(s,*e) :若栈存在且非空,用e返回s的栈顶元素
Push(*s,e) : 若栈存在,插入新元素e到栈s中并称为栈顶元素
Pop(*s,*e) :删除栈s中栈顶元素,并用e返回其值。
StackLenth(s) :返回栈s的元素个数。
endADT
4.栈的线性储存结构
4.1栈的顺序结构
栈是线性表的特例,那么栈的顺序储存也是线性表顺序的简化,我们简称顺序栈。线性表是用数组来实现的,用数组下标为零的一端来做为栈底,定义一个top标量,指示栈顶元素在数组中的位置
栈的结构定义:
typedef int SElemType SLemType看实际情况来定,这里定义为int
typedef struct
{
SLemType data[MAXSIZE];
int top; //用于栈顶指针
}SqStack;
例如MAXSIZE为5
栈中有两个元素,top等于1;栈中没有元素(栈空),top为-1;栈满的时候为4。
4.2栈的顺序结构,进栈操作
对于栈的插入,即栈的进栈操作。
/插入元素e为新的栈顶元素/
Stack Push(SqStack *s,SLemType e)
{
if(s->top == MAXSIZE - 1)
{retrun ERROR;}
s->top++; //栈顶指针加一位
s->data[s->top]=e; //将新插入元素赋值给栈顶空间
retrun OK;
}
4.3栈的出栈操作
Stack Pop(SqStack *s,SElmType *e)
{
if(s->top==-1)
{return ERROR;}
*e=s->data[s->top];
s->top--;
return OK;
}
5.栈的链式存储结构及其实现
5.1 栈的链式存储结构
简称链栈,把栈顶节点当做链表的头节点,栈为空的时候是头指针指向空,所以为top=NULL;
typedef struct StackNode//结点链指针
{
SElemType data;
struct StackNode *next;
} StackNode,*LinkStackPtr;
typedef struct LinkStack//链式栈
{
LinkStackPtr top;
int count;
}LinkStack;
PS:关于结构体定义链表的具体说明见:
5.2.栈的链式存储结构——进栈操作
Status Push(LinkStack *S,SElemType e)
{
LinkStackPtr s=(LinkStack)malloc(sizeof(StackNode));
s->next=S->top;//当前栈顶元素赋值给新节点的直接后继
s->data=e;
S->top=s;//将新节点s赋值给栈顶指针
S->count++;
return OK;//status返回状态
}
(Status ,status Linklist_L(Linklist &L,int i,…) 的函数类型是Status,即函数调用结果要送返状态值,例如成功失败。)
5.3.栈的链式储存结构——出栈操作
简单三步:1.假设变量p用来储存要删除的栈顶节点 2.将栈顶指针下移一位 3. 释放p
//若栈不空,删除S的栈顶元素,用e返回其值,并返回OK,否则返回ERROR
Status Pop(LinkStack *S,SElemType *e)
{
}