【数据结构学习】栈(线性表一种特殊情况)

目录

栈的基础知识

栈的顺序存储结构

两栈共享空间 


栈的基础知识 

栈的定义:是限定仅在表尾进行插入与删除的线性表,后进先出,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;
}

运行结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Roy1Zz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值