参考资料:李春葆主编的数据结构教程第六版
栈(stack)的定义:
栈(又名:堆栈)是一种只能在一段进行插入或删除操作的线性表(受限的线性表)
栈的主要特点:先进后出/后进先出
基本概念:a.栈顶 (Top):(进出口)表中允许进行插入或删除操作的一端。
b.栈底 (Bottom):栈顶和栈底是相对而言的,一端被称作为栈顶,相对的,另一端就被称作为栈底。
c.进栈/入栈(Push):栈的插入操作。
d.出栈/退栈(Pop):栈的删除操作。
e.空栈:栈中没有元素/(s->Top==-1;)
f. 满栈:栈中已放满元素/(s->Top==MaxSize-1)
判断出栈序列是否合法
在出栈结果中,任意选取一个位置i,该位置右边的所有小于位置i元素的,必须是降序序列。
eg:元素的进栈序列为12345,能否得到31425的出栈序列
任意选取=>若选31425中的第一个元素3,该位置右边的所有小于3的元素的序列为1 2,为升序,故得不到3142的出栈序列。(理解:若3被取出,且1和2两元素在3之后被取出,2被取出才能再取出2下面的1(1比2先进,所以要后出,满足栈先进后出的特点))。
n个不同元素通过一个栈产生的出栈序列的个数为
/(n+1)(利用递归思想+卡特兰数)
以n=4为例:
栈的顺序存储结构及基本运算的实现
//声明顺序栈的类型
typedef struct {//顺序存储由数组和栈顶指针两部分组成
int data[Maxsize];
int top;
}Sqstack;
//初始化栈
void InitStack(Sqstack *&s){
s=(Sqstack *)malloc(sizeof(Sqstack));
s->top=-1;//top(栈顶指针)指向-1时,为空栈,表明任何一个空间都没有被指向到
}
//销毁栈
void DestroyStack(Sqstack *&s){
free(s);
}
//判断栈是否为空
bool StackEmpty(Sqstack *s){
return (s->top==-1);
}
//进栈(push)
bool Push(Sqstack *&s,int e){
//First 判断是否为满栈,若为满栈会出现上溢出现象,导致数据不能再入栈
if(s->top==Maxsize-1)
return false;
else{
s->data[++s->top]=e;
return true;
}
}
//退/出栈(pop)
bool Pop(Sqstack *&s,int &e){
if(s->top==-1)
return false;
else{
e=s->data[s->top--];
return true;
}
}
//取栈顶元素
bool GetTop(Sqstack *&s,int &e){
if(s->top==-1)
return false;
else{
e=s->data[s->top];
return true;
}
}
共享栈
1.栈空=>栈1为空栈的条件是top1==-1,栈2为空栈的条件是top==MaxSize;
2.栈满的条件=>top2-top1==1
3.入栈操作:栈1插入操作:s->data[++s->top1]=e;栈2插入操作:s->data[--top2]=e;
4.出栈操作:栈1删除操作:e=s->data[s->top--];栈2插入操作:e=s->data[top2++];
栈的链式存储结构及其基本运算的实现
采用链式存储结构的栈称为链栈。
//声明链栈的类型
typedef struct linknode{//每个节点由数据和指针两部分组成
int data;
struct linkNode *next;//指向结构体linknode的指针
}LinkStNode; //链栈结点类型
对于建立链表来说分为头插法和尾插法
头插法更为方便(top指针即为s->next[头结点]),若用尾插法则top指针在表尾,需要另外定义,且不易进行出栈操作,top指针需要指向出栈元素的上一个元素,但只有next指针,用双向链表就更为复杂。
//初始化栈
void InitStack(LinkStNode *&s){
s=(LinkStNode *)malloc(sizeof(LinkStNode));
s->next=NULL;// s->next即top指针指向为空
}
//销毁栈
void DestoryStsck(LinkStNode * &s){
LinkStNode * pre=s, * p=s->next;
while(p!=NULL){
free(pre);
pre=p;
p=pre->next;
}
free(pre);
}
//判断栈是否为空
bool StackEmpty(LinkStNode *s){
return (s->next==NULL);
}
//进栈
bool Push(LinkStNode *&s,int e){//链栈不会出现上溢出的现象
LinkStNode * p;
p=(LinkStNode *)malloc(sizeof(LinkStNode));
p->data=e;
p->next=s->next;
s->next=p;
return true;
}
//出栈-->一直出栈直至s->next==NUll就是销毁栈
bool Pop(LinkStNode *&s,int &e){
LinkStNode *p=s->next;
if(s->next==NULL)
return false;//防止下溢出
e=p->data;
s->next=p->next;
free(p);
return true;
}
//取栈顶元素
bool GetTop(LinkStNode *s,int &e){
if(s->next==NULL)
return false;
e=s->next->data;
return true;
}