嵌入式全栈开发学习笔记---数据结构(顺序栈)

目录

栈的概念

定义顺序栈

栈的初始化

进栈操作

判断栈是否为空

获取栈顶元素

出栈操作

清空栈操作

销毁栈操作

完整代码

Stack.c

Stack.h

Main.c


上节我们讲解了双向循环链表,这节开始学习栈!

栈的概念

栈是一个特殊的线性表,只能在一端操作;

栈顶(top):允许操作的一端;

栈底(bottom):不允许操作的一端

特点是:最先进栈的最后出栈

通俗来讲,最先进去的被压在最下面,所以只能最后才出来。

实现栈有两种方式:顺序存储(顺序栈),链式存储(链栈)

即我们可以用数组来实现,也可以用链表来实现。

本节先来讲用数组来存放栈结构。

栈顶我们一般需要一个栈顶指针,但是数组没有指针,只有下标

此时栈顶3的下标就是2,栈底1的下标是0。

当我们初始化一个空栈的时候,栈顶指针(下标)应该设置为-1,如果设置为0的话就还不能表示空栈。

我们在程序上如果来表示一个栈呢?

我们还是用结构体来表示:

struct Stack

{

int*data;//指向栈所在的内存

int top;//栈顶

}

只要知道栈顶在哪了,就知道这个栈的容量有多大了。

接下来用代码来实现栈的一些操作

先创建一个目录seqStack

定义顺序栈

创建一个stack.h文件

在这个头文件里面定义一个栈和栈的容量,以及成功/失败的宏定义

然后main.c中创建一个栈

栈的初始化

Stack.c

在stack.h中声明一下这个函数

Main.c

运行结果:

进栈操作

代码演示:

Stack.c

栈的结构体中,我们可以把data看成是数组名,top是下标

在stack.h中声明一下这个函数

Main.c

运行结果:

判断栈是否为空

Stack.c

在stack.h中声明一下这个函数

Main.c

运行结果

获取栈顶元素

注意栈顶元素的值是否正好是1000(SUCCESS)或者1001(FAILURE),我们这里定义的随机数是0~20,随机不存在这个冲突的问题,以后再开发中可能需要注意。

代码演示:

Stack.c

在stack.h中声明一下这个函数

Main.c

运行结果:

出栈操作

出栈时需要返回出栈的元素,top向下移动

Stack.c

在stack.h声明一下这个函数

Main.c

运行结果

注意:栈是不存在遍历操作的。

清空栈操作

因为顺序栈的内存是连续的,所以清空操作只需要让top等于-1表示空栈就行了。

Stack.c

在stack.h声明一下这个函数

Main.c

运行结果:

清空成功后我们可以获取栈顶元素验证一下是否真的清空了

运行结果

的确清空了

销毁栈操作

Stack.c

在stack.h声明一下这个函数

Main.c

运行结果

按理来说销毁栈时候就不能进栈了,所以可以调用一个进栈的代码验证一下是否真的销毁成功

运行结果

出现了段错误,是因为销毁的时候,data置为了空指针,但是进栈的时候我们只判断了s是否为空指针,所以我们还需要在进栈时候判断一些data是否为空指针

再次运行

的确销毁成功了。

完整代码

Stack.c

#include "stack.h"
#include <stdlib.h>//NULL的头文件

//栈的初始化
int InitStack(Stack*s)
{
	//入参判断
	if(NULL==s)
	{
		return FAILURE;
	}

	s->data=(int*)malloc(sizeof(int)*SIZE);//申请空间
	if(NULL==s->data)
	{
		return FAILURE;//申请失败
	}

	s->top=-1;//栈顶初始化为-1

	return SUCCESS;
	
}

//进栈操作
int PushStack(Stack *s,int num)
{
	if(NULL==s||NULL==s->data)
	{
		return FAILURE;
	}

	//判断栈是否已满
	if(s->top>=SIZE-1)
	{
		return FAILURE;
	}

	s->data[++s->top]=num;//top先作为下标移动到第一个位置,然后再放入num

	return SUCCESS;

}

//判断栈是否为空
int EmptyStack(Stack s)
{
	return (s.top==-1)? SUCCESS:FAILURE;
}

//获取栈顶元素
int GetTop(Stack s)
{
	return (s.top==-1)? FAILURE:s.data[s.top];
}

//出栈操作
int PopStack(Stack *s)
{
	if(NULL==s)
		return FAILURE;

	//判断栈是否为空
	if(s->top==-1)
		return FAILURE;

	return s->data[s->top--];//先返回,top再减减
}

//清空操作
int ClearStack(Stack*s)
{
	if(NULL==s)
		return FAILURE;

	s->top=-1;

	return SUCCESS;
}

//销毁操作
int DestroyStack(Stack*s)
{
	if(NULL==s)
		return FAILURE;

	free(s->data);
	//释放掉后data成为野指针,所以要置为空指针
	s->data=NULL;

	return SUCCESS;
}



Stack.h

#ifndef _STACK_H
#define _STACK_H

#define SIZE 10   //栈的容量
#define SUCCESS 1000
#define FAILURE 1001

//表示栈的结构体
typedef struct seqStack
{
	int *data;
	int top;
}Stack;


int InitStack(Stack*s);
int PushStack(Stack *s,int num);
int EmptyStack(Stack s);
int GetTop(Stack s);
int PopStack(Stack *s);
int ClearStack(Stack*s);
int DestroyStack(Stack*s);



#endif

Main.c

#include "stack.h"
#include <stdio.h>
#include <time.h>//随机数头文件
#include <stdlib.h>

int main()
{
	//创建栈
	Stack s;

	//栈的初始化
	int ret=InitStack(&s);
	if(SUCCESS==ret)
	{
		printf("栈初始化成功\n");
	}
	else
	{
		printf("栈初始化失败\n");
	}

	//进栈操作
	int i,num;
	srand(time(NULL));
	for(i=0;i<5;i++)//进5个
	{
		num=rand()%20;
		ret=PushStack(&s,num);//因为等会儿要改栈顶,所以传s的地址
		if(SUCCESS==ret)
		{
			printf("%d 进栈成功\n",num);
		}
		else
		{
			printf("%d 进栈失败\n",num);//栈满了
		}
	}

	//判断栈是否为空
	ret=EmptyStack(s);
	if(ret==SUCCESS)
	{
		printf("栈为空\n");
	}
	else
	{
		printf("栈不为空\n");
	}

	//获取栈顶元素
	ret=GetTop(s);
	if(FAILURE==ret)
	{
		printf("不存在栈顶元素\n");
	}
	else
	{
		printf("栈顶元素是%d\n", ret);
	}

	//出栈操作
	for(i=0;i<5;i++)//出栈5个元素
	{
		ret=PopStack(&s);//一会儿要改top,所以取地址
		if(FAILURE==ret)
		{
			printf("出栈失败\n");
		}
		else
		{
			printf("%d 出栈成功\n",ret);
		}
	}

	//清空操作
	ret=ClearStack(&s);
	if(SUCCESS==ret)
	{
		printf("清空成功\n");
	}
	else
	{
		printf("清空失败\n");
	}

	//获取栈顶元素,验证是否清空了
	ret=GetTop(s);
	if(FAILURE==ret)
	{
		printf("不存在栈顶元素\n");
	}
	else
	{
		printf("栈顶元素是%d\n", ret);
	}

	//销毁操作
	ret=DestroyStack(&s);//释放掉data指向的空间后要修改为NULL,所以需要传地址
	if(SUCCESS==ret)
	{
		printf("销毁成功\n");
	}
	else
	{
		printf("销毁失败\n");
	}


	//进栈操作,验证是否真的销毁成功
	srand(time(NULL));
	for(i=0;i<5;i++)//进5个
	{
		num=rand()%20;
		ret=PushStack(&s,num);//因为等会儿要改栈顶,所以传s的地址
		if(SUCCESS==ret)
		{
			printf("%d 进栈成功\n",num);
		}
		else
		{
			printf("%d 进栈失败\n",num);//栈满了
		}
	}



	return 0;
}

顺序栈我们就介绍完毕了,下节开始讲链栈!

QQ交流群:963138186

本篇就到这里,下篇继续!欢迎点击下方订阅本专栏↓↓↓

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Vera工程师养成记

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

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

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

打赏作者

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

抵扣说明:

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

余额充值