【栈、队列和数组之栈】


一、栈的定义

栈是只允许在一端进行插入或者删除的线性表。
栈
在插入数据的时候只允许从栈顶插入,如图所示,在进行进栈的操作时,次序依次是a1,a2,a3,a4,a5;而出栈的时候次序则是a5,a4,a3,a2,a1,所以栈的操作特性是先进后出。

二、栈的顺序存储结构

1.顺序栈的实现

利用一组地址连续的存储单元存放自栈底到栈顶的数据元素,并增加一个指针(top)指向当前栈顶的位置

#define MaxSize 50
typedef int ElemType;
typedef struct {
	ElemType data[MaxSize];  //存放栈中元素
	int top;  //栈顶指针
}SqStack;

栈顶指针:S.top;初始化:S.top=-1;栈顶元素:S.data[S.top]
进栈操作:先检查栈是否满了,没满的话,则栈顶指针先+1,再送值到栈顶元素
出栈操作:先检查栈是否为空,不为空的话,则先取栈顶的值,再将栈顶指针-1
栈空的条件:S.top==-1;栈满的条件:S.top==MaxSize-1;栈长:S.top+1

2.顺序栈的基本运算

(1)栈的初始化

//初始化空栈
void InitStack(SqStack& S)
{
	S.top = -1;
}

(2)判断栈是否为空

//判断是否为空栈
bool StackEmpty(SqStack& S)
{
	if (S.top == -1)
		return true;
	else
		return false;
}

(3)入栈操作

//入栈
bool Push(SqStack& S, ElemType x)
{
	if (S.top == MaxSize - 1)  //判断栈是否满了
	{
		return false;
	}
	S.data[++S.top] = x;  //指针先加1,在入栈
	return true;
}

(4)出栈操作

//出栈
bool Pop(SqStack& S, ElemType x)
{
	if (S.top == -1)
	{
		return false;
	}
	x = S.data[S.top--];  //先出栈之后指针再减1
	return true;
}

(5)读取栈顶元素

//读取栈顶元素
bool GetTop(SqStack S, ElemType& x)
{
	if (S.top == -1)
	{
		return false;
	}
	x = S.data[S.top];  //x存放栈顶的元素
	return true;
}

读取栈顶元素

三、栈的链式存储结构

1.链栈的实现

链栈的优点是便于多个栈共享存储空间和提高效率,且不存在栈满上溢的情况。栈的链式存储类型如下:

typedef int ElemType;
typedef struct Linknode {
	ElemType data;  //数据域
	struct Linknode* next;  //指针域
}Linknode, * LiStack;  //栈的类型定义

2.链栈的基本运算

(1)初始化

//初始化
void InitLiStack(LiStack& S)
{
	S = NULL;
}

//判断栈是否为空
bool LiStackEmpty(LiStack S)
{
	if (S == NULL)
		return true;
	else
		return false;
}

(2)入栈操作

//入栈
bool push(LiStack& S, ElemType x)
{
	Linknode* p;
	p = (LiStack)malloc(sizeof(Linknode));	//新建结点,为其分配空间
	p->data = x;	//将新结点数据域赋值为X
	p->next = S;	//将指向原栈顶结点的指针用p->next替换
	S = p;	//将指向新结点的指针用S替换,以方便新结点的入栈
	return true;
}

(3)出栈操作

//出栈
bool pop(LiStack& S, ElemType x)
{
	Linknode* p;
	if (S == NULL)
	{
		return false;
	}
	else {
		x = S->data;	//将栈顶元素数据域赋值给x
		p = S;	//将指向栈顶元素的指针替换为p
		S = S->next;	//S->next指向下一结点,现用S指向这个结点,相当于删除了原先的S->next
		free(p);	//释放结点p(即原栈顶元素)
		p = NULL;
	}
	return true;
}

(4)获取栈顶元素

//获取栈顶元素
bool GetTop(LiStack S, ElemType& x)
{
	if (S == NULL)
	{
		return false;
	}
	else {
		x = S->data;
	}
	return true;
}

链栈
链式存储一系列操作与链表几乎相似,入栈和出栈都是在表头进行。

三、整体代码

顺序存储:

#include<stdio.h>
#include<stdlib.h>

#define MaxSize 50
typedef int ElemType;
typedef struct {
	ElemType data[MaxSize];
	int top;
}SqStack;

//初始化空栈
void InitStack(SqStack& S)
{
	S.top = -1;
}
//判断是否为空栈
bool StackEmpty(SqStack& S)
{
	if (S.top == -1)
		return true;
	else
		return false;
}
//入栈
bool Push(SqStack& S, ElemType x)
{
	if (S.top == MaxSize - 1)  //判断栈是否满了
	{
		return false;
	}
	S.data[++S.top] = x;  //指针先加1,在入栈
	return true;
}
//出栈
bool Pop(SqStack& S, ElemType x)
{
	if (S.top == -1)
	{
		return false;
	}
	x = S.data[S.top--];  //先出栈之后指针再减1
	return true;
}
//读取栈顶元素
bool GetTop(SqStack S, ElemType& x)
{
	if (S.top == -1)
	{
		return false;
	}
	x = S.data[S.top];  //x存放栈顶的元素
	return true;
}
int main()
{
	SqStack S;
	InitStack(S);
	ElemType x;
	bool flag;
	Push(S, 2);
	Push(S, 5);
	Push(S, 9);
	flag = StackEmpty(S);
	if (flag)
	{
		printf("此栈为空栈:\n"); //因为上面插入了数据,所以运行不显示此语句
	}
	flag = GetTop(S, x);
	if (flag)
	{
		printf("获取栈顶元素为:%d\n", x);
	}
	flag = Pop(S, x);
	if (flag)
	{
		printf("弹出栈顶元素为:%d\n", x);
	}
	return 0;
}

链式存储:

#include<stdio.h>
#include<stdlib.h>

typedef int ElemType;
typedef struct Linknode {
	ElemType data;  //数据域
	struct Linknode* next;  //指针域
}Linknode, * LiStack;  //栈的类型定义

//初始化
void InitLiStack(LiStack& S)
{
	S = NULL;
}

//判断栈是否为空
bool LiStackEmpty(LiStack S)
{
	if (S == NULL)
		return true;
	else
		return false;
}

//入栈
bool push(LiStack& S, ElemType x)
{
	Linknode* p;
	p = (LiStack)malloc(sizeof(Linknode));	//新建结点,为其分配空间
	p->data = x;	//将新结点数据域赋值为X
	p->next = S;	//将指向原栈顶结点的指针用p->next替换
	S = p;	//将指向新结点的指针用S替换,以方便新结点的入栈
	return true;
}

//出栈
bool pop(LiStack& S, ElemType x)
{
	Linknode* p;
	if (S == NULL)
	{
		return false;
	}
	else {
		x = S->data;	//将栈顶元素数据域赋值给x
		p = S;	//将指向栈顶元素的指针替换为p
		S = S->next;	//S->next指向下一结点,现用S指向这个结点,相当于删除了原先的S->next
		free(p);	//释放结点p(即原栈顶元素)
		p = NULL;
	}
	return true;
}
//获取栈顶元素
bool GetTop(LiStack S, ElemType& x)
{
	if (S == NULL)
	{
		return false;
	}
	else {
		x = S->data;
	}
	return true;
}
int main()
{
	LiStack S;
	InitLiStack(S);
	ElemType x;
	bool ret;
	push(S, 2);
	push(S, 3);
	push(S, 4);
	push(S, 5);
	ret = LiStackEmpty(S);
	if (ret)
	{
		printf("此栈为空栈\n");
	}
	else
	{
		printf("此栈不为空\n");
	}
	ret = GetTop(S, x);
	if (ret)
	{
		printf("获取栈顶元素为:%d\n", x);
	}
	ret = pop(S, x);
	if (ret)
	{
		printf("弹出栈顶元素为:%d\n", x);
	}
	return 0;
}

总结

栈的话其实算是一个小知识点,需要记住对栈的操作是只能对某一端进行操作即可,顺序存储和链式存储大同小异,跟前面的线性表几乎一致。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值