目录
前言
一、顺序栈的定义
二、顺序栈的c++语言结构描述表示
三、顺序栈中基本操作的实现
3.1顺序栈的初始化
3.2判断顺序栈是否为空
3.3求顺序栈的长度
3.4清空顺序栈
3.5销毁顺序栈
3.6顺序栈的入栈
3.7顺序栈的出栈
3.8求栈顶元素
3.9遍历顺序栈
四、顺序栈的代码实现
五、测试结果
五、总结
前言
本文参考王卓老师的数据结构视频和严蔚敏老师的《数据结构》
一、顺序栈的定义
栈:操作受限的线性表,限定仅在表尾进行插入和删除操作的线性表,即后进先出。这一端被称为栈顶,相对地,把另一端称为栈底。
顺序栈:用顺序结构存储的栈
例子:类似子弹压入弹夹,后放入的子弹可以先从弹夹弹出来。
特点:简单方便,但是容易溢出(上溢或者下溢)
二、顺序栈的c++语言结构描述表示
代码如下(示例):
typedef struct sqstack{
int *top;//栈顶指针
int *base;//栈底指针
int stackSize;//栈的最大容量
}stack;
三、顺序栈中基本操作的实现
3.1顺序栈的初始化
数组用c++的new来动态开辟
当内存不够的时候,也即是s.base为空,则直接结束
不为空的时候,则栈的栈顶指针与栈底指针都指向同一位置
代码如下(示例):
void initStack(stack &s)
{s.base=new int[MaxSize];if(!s.base) exit(0);//内存分配失败,结束s.top=s.base;//初始的时候栈的top与base相等 s.stackSize=MaxSize;//栈的最大容量
}
3.2判断顺序栈是否为空
栈顶指针与栈底指针都指向同一位置,即s.base==s.top的时候,则栈为空,返回1
否则,不为空,返回0
代码如下(示例):
int isEmpty(stack s)
{if(s.base==s.top)return 1;//表示为空,无元素return 0;//不为空
}
3.3求顺序栈的长度
长度即为有多少个元素,可以用s.top-s.base
代码如下(示例):
int stackLength(stack s)
{return s.top-s.base;
}
3.4清空顺序栈
当s.base不为空的时候,让s.top(栈顶指针)直接指向s.base(栈底),则把所有的元素逻辑上清空了
而当s.base为空的时候,则栈已经被销毁了,无需清空
代码如下(示例):
void CleanStack(stack &s)
{if(s.base){s.top=s.base;cout<<"成功清空"<<endl;}elsecout<<"栈已经被销毁,无需清空"<<endl;
}
3.5销毁顺序栈
从物理层次销毁
也即是用delete将整个s.base从内存中删除
代码如下(示例):
void DestoryStack(stack &s)
{if(s.base){delete s.base;s.stackSize=0;s.base=NULL;s.top=NULL;cout<<"成功销毁"<<endl;}elsecout<<"栈已经被销毁,无需销毁"<<endl;
}
3.6顺序栈的入栈
首先判断栈是否已经满了,如果满了则无法入栈,否则可以入栈
代码如下(示例):
void push(stack &s,int e)
{if((s.top-s.base)==s.stackSize)cout<<"栈满了,无法添加新元素"<<endl;else{*(s.top)=e;s.top++; cout<<"添加成功"<<endl;}
}
3.7顺序栈的出栈
首先判断栈是否为空,如果为空,则无法出栈,否则可以出栈
代码如下(示例):
void pop(stack &s,int &e)
{if(isEmpty(s)){cout<<"栈为空,无法弹出"<<endl;} else{s.top--;e=*(s.top);cout<<"成功弹出"<<endl; }
}
3.8求栈顶元素
先判断栈是否为空,为空则无法求栈顶元素,否则可以求栈顶元素
代码如下(示例):
int top(stack s)
{if(isEmpty(s)){cout<<"栈为空,没有栈顶元素"<<endl;return -1;}else{s.top--;return *(s.top);}
}
3.9遍历顺序栈
从栈底开始遍历
代码如下(示例):
void traverse(stack s)
{int length=stackLength(s);if(length>0){cout<<"顺序栈的元素为:(从栈底开始遍历)"<<endl;for(int i=0;i<length;i++)cout<<s.base[i]<<" ";} elsecout<<"顺序栈为空"<<endl;
}
四、顺序栈的代码实现
#include <iostream>
using namespace std;
const int MaxSize=100;
typedef struct sqstack{int *top;//栈顶指针int *base;//栈底指针int stackSize;//栈的最大容量
}stack;
void initStack(stack &s)
{s.base=new int[MaxSize];if(!s.base) exit(0);//内存分配失败,结束s.top=s.base;//初始的时候栈的top与base相等 s.stackSize=MaxSize;//栈的最大容量
}
int isEmpty(stack s)
{if(s.base==s.top)return 1;//表示为空,无元素return 0;//不为空
}
int stackLength(stack s)
{return s.top-s.base;
}
void CleanStack(stack &s)
{if(s.base){s.top=s.base;cout<<"成功清空"<<endl;}elsecout<<"栈已经被销毁,无需清空"<<endl;
}
void DestoryStack(stack &s)
{if(s.base){delete s.base;s.stackSize=0;s.base=NULL;s.top=NULL;cout<<"成功销毁"<<endl;}elsecout<<"栈已经被销毁,无需销毁"<<endl;
}
//入栈
void push(stack &s,int e)
{if((s.top-s.base)==s.stackSize)cout<<"栈满了,无法添加新元素"<<endl;else{*(s.top)=e;s.top++; cout<<"添加成功"<<endl;}
}
//出栈
void pop(stack &s,int &e)
{if(isEmpty(s)){cout<<"栈为空,无法弹出"<<endl;} else{s.top--;e=*(s.top);cout<<"成功弹出"<<endl; }
}
int top(stack s)
{if(isEmpty(s)){cout<<"栈为空,没有栈顶元素"<<endl;return -1;}else{s.top--;return *(s.top);}
}
void traverse(stack s)
{int length=stackLength(s);if(length>0){cout<<"顺序栈的元素为:(从栈底开始遍历)"<<endl;for(int i=0;i<length;i++)cout<<s.base[i]<<" ";} elsecout<<"顺序栈为空"<<endl;
}
void menu()
{cout<<"**********************************"<<endl;cout<<"1.初始化"<<endl;cout<<"2.判断栈是否为空"<<endl;cout<<"3.求栈的长度"<<endl;cout<<"4.清空栈"<<endl;cout<<"5.销毁栈"<<endl;cout<<"6.入栈"<<endl;cout<<"7.出栈"<<endl;cout<<"8.求栈顶元素"<<endl;cout<<"9.遍历顺序栈"<<endl;cout<<"10.退出"<<endl;cout<<"**********************************"<<endl;
}
int main()
{int choice;stack s;int e1,e2;while(1){menu();cin>>choice;switch(choice){case 1:initStack(s);cout<<"初始化成功"<<endl;break;case 2:if(isEmpty(s))cout<<"栈为空"<<endl;elsecout<<"栈不为空"<<endl; break;case 3:cout<<"栈的长度为"<<stackLength(s)<<endl;break;case 4:CleanStack(s);break;case 5:DestoryStack(s);break; case 6:cout<<"请输入想要入栈的元素值:"<<endl;cin>>e1;push(s,e1);break;case 7:pop(s,e2);cout<<"弹出的元素为"<<e2<<endl;break;case 8:if(top(s)!=-1)cout<<"栈顶元素为"<<top(s)<<endl;break;case 9:traverse(s);cout<<endl;break;case 10:cout<<"成功退出"<<endl;exit(0);default:cout<<"输入有误,请重新输入"<<endl;break; } }
}
五、测试结果
图一
图二
图三
图四
图五
图六
图七
图八
图九
图十
图十一
六、总结
栈是一种操作受限的线性表,虽然操作受限,但是与线性表有点类似,只不过栈的插入和删除都在表尾而已。而我在本文中实现的顺序栈有点类似顺序表。我们也需要注意到顺序栈虽然实现简单,但是其容易发生溢出,在栈满的时候,还要入栈,则会上溢,而在栈空的时候,还要出栈,则会下溢,针对这个问题,我将在下一篇文章的链栈解决这个问题。