目录
栈的基础知识
栈的定义:是限定仅在表尾进行插入与删除的线性表,后进先出,LIFO结构(Last In First Out)
栈顶与栈底:允许插入与删除的一端,另一端为栈底。
空栈:不含任何数据元素的栈称为空栈
栈的插入:叫做进栈,压栈,入栈,类似子弹入弹夹。
栈的删除:叫做出栈,弹栈,类似弹夹子弹出弹夹。
注意:最先进栈的元素,不一定最后出栈,但一定满足后进先出原则。
经典举例:3个整型元素1,2,3分别依次进栈,求出栈顺序
列举:(1)1,2,3进,3,2,1出 (2)1进,1出,2进,2出,3进,3出
(3)1进,2进,1出,2出,3进,3出 (4)1进,1出,2进,3进,3出,2出
(5)1进,2进,2出,3进,3出,1出 共5种出入栈情况
注意:出栈顺序不可能是312,因为这样1,2的入栈顺序反了,不符合题意。
栈的顺序存储结构
简单来说,栈的顺序存储结构就是利用数组存储数据元素,所谓栈顶与栈底,也可以理解为数组的存放元素的当前位置与起始位置,用变量top来指示栈顶元素在数组中的位置,如图所示。
以下为代码实现:
1.栈的结构定义
#include <bits/stdc++.h>
#define MaxSize 10
using namespace std;
//1.定义栈的结构体
typedef struct{
int top; //统计栈中有多少元素,data[top]是栈顶
int data[MaxSize]; //数组用于存放数据
}Stack;
Stack s = {-1,{0}};
2.判断栈是否为空
bool isEmpty(){
bool flag = false; //默认栈没有空
if(s.top == -1) //如果栈为空栈
flag = true;
return flag;
}
3.判断栈是否满了
bool isFull(){
bool flag = false; //默认栈没有满
if(s.top == MaxSize-1) //如果栈满了
flag = true;
return flag;
}
4.压数据元素进栈
void Push(int e){
if(!isFull()){//如果栈没满
s.top++;
s.data[s.top] = e;
}else{
printf("栈满了,停止进栈");
exit(0);
}
}
5.弹数据元素出栈
int Pop(){
if(!isEmpty()){
s.top--;
int e = s.data[s.top+1];
return e;
}else{
printf("空栈,停止出栈");
exit(0);
}
}
完整代码如下(运行环境为:DevC++5.11)
#include <bits/stdc++.h>
#define MaxSize 10
using namespace std;
//1.定义栈的结构体
typedef struct{
int top; //统计栈中有多少元素,data[top]是栈顶
int data[MaxSize]; //数组用于存放数据
}Stack;
Stack s = {-1,{0}};
//2.判断栈是否为空
bool isEmpty(){
bool flag = false; //默认栈没有空
if(s.top == -1) //如果栈为空栈
flag = true;
return flag;
}
//3.判断栈是否满了
bool isFull(){
bool flag = false; //默认栈没有满
if(s.top == MaxSize-1) //如果栈满了
flag = true;
return flag;
}
//4.压数据元素进栈
void Push(int e){
if(!isFull()){//如果栈没满
s.top++;
s.data[s.top] = e;
}else{
printf("栈满了,停止进栈");
exit(0);
}
}
//5.压数据元素出栈
int Pop(){
if(!isEmpty()){
s.top--;
int e = s.data[s.top+1];
return e;
}else{
printf("空栈,停止出栈");
exit(0);
}
}
int main(){
int data[10] = {1,2,3,4,5,6,7,8,9,10},i = 0;
printf("元素入栈\n");
while(!isFull()){
printf("%d\t",data[i]);
Push(data[i]);
i++;
}
printf("\n元素出栈\n");
while(!isEmpty())
printf("%d\t",Pop());
return 0;
}
运行结果:
两栈共享空间
简单来说,两栈共享空间就是一个数组分给两个数据类型相同的栈共用,有两个栈顶指针top1,top2。
有以下极端情况:
栈1为空:top1= -1
栈2为空:top2= MaxSize
栈满:top1+1==top2
以下为代码实现:
#include <bits/stdc++.h>
#define MaxSize 10
using namespace std;
//1.定义栈的结构体
typedef struct{
int top1,top2;//两个栈的栈顶指针
int data[MaxSize];
}DoubleStack;
//2.定义结构体变量并初始化
DoubleStack s = {-1,MaxSize,{0}};
//以下函数形参中的num为栈名
//3.判断栈1是否为空栈
bool isEmpty1(int num){
bool flag = false;
if(num==1 && s.top1==-1)
flag = true;
return flag;
}
//4.判断栈2是否为空栈
bool isEmpty2(int num){
bool flag = false;
if(num==2 && s.top2 == MaxSize)
flag = true;
return flag;
}
//5.判断共享栈是否满了
bool isFull(){
bool flag = false;
if(s.top1+1 == s.top2)
flag = true;
return flag;
}
//6.插入数据元素进栈
void Push(int e,int num){
if(isFull()){
printf("栈满了不能插入元素");
exit(0);
}else{
if(num == 1){ //栈1是否有元素进栈
s.top1++; //先top1前移后赋给数组元素值
s.data[s.top1] = e;
}else if(num == 2){ //栈2是否有元素进栈
s.top2--;//先top2后移再赋给数组元素值
s.data[s.top2] = e;
}
}
}
//7.弹出数据元素出栈
int Pop(int num) {
if(num == 1){
if(isEmpty1(num)){
printf("栈1是空栈,不能弹出数据元素");
exit(0);
}else{
int e1 = s.data[s.top1];
s.top1--;
return e1;
}
}
if(num == 2){
if(isEmpty2(num)){
printf("栈2是空栈,不能弹出数据元素");
exit(0);
}else{
int e2 = s.data[s.top2];
s.top2++;
return e2;
}
}
}
int main(){
int stackname,i = 0;
printf("请输入栈名(1/2):");
cin >> stackname;
int data[10]={1,3,5,7,9,2,4,6,8,10};
printf("元素入栈\n");
while(!isFull()){
printf("%d\t",data[i]);
Push(data[i],stackname);
i++;
}
printf("\n元素出栈\n");
while(!(isEmpty1(stackname)||isEmpty2(stackname)))
printf("%d\t",Pop(stackname));
return 0;
}
运行结果: