(数据结构)栈的实现

今天船长计划用简单的方式向大家介绍数据结构中重要知识点——

此篇文章中,我将带领大家一步一步用C语言将栈结构给实现出来;全文干货,强烈建议观众老爷们先赞后看哦!

目录

1.栈的概念及结构

2.栈的实现

2.1头文件的包含

2.2构造结构体

2.3定义相应函数

2.3实现相应函数

初始化、销毁

入栈、出栈

获取栈顶、获取栈顶对应号数

验空函数

3.结语 


1.栈的概念及结构

栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。

进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶

出栈:栈的删除操作叫做出栈。出数据也在栈顶

栈的进栈和出栈具体形式如下图所示:


2.栈的实现

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。

原因:

  • 因为数组在尾上插入数据的代价比较小;
  • 数组连续储存在栈区,相比堆区缓存更加友好;
  • 另外数组一般属于高级语言语法中的基本类型,结构简单,有利于编译器做寄存器优化、常量折叠、无用代码精简等,优化完速度还要更快。

2.1头文件的包含

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>//对应下文验空函数

2.2构造结构体

栈结构分为静态结构和动态结构,现实中动态结构更为常用,因此我们这次主要实现栈的动态结构

typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;
	int capacity;
}ST;

2.3定义相应函数

//初始化
void StackInit(ST* ps);
//销毁
void StackDestory(ST* ps);
//入栈
void StackPush(ST* ps, STDataType x);
//出栈
void StackPop(ST* ps);

//获取头部
STDataType StackTop(ST* ps);
//获取号数
int StackSize(ST* ps);
//验空
bool StackEmpty(ST* ps);

2.3实现相应函数

初始化、销毁

初始化主要是将指针置空,数据归零;

销毁的步骤也和初始化差不多,但是在此之前要多一步:释放空间,解除占用

//初始化
void StackInit(ST* ps)
{
	assert(ps);//检查*ps是否为空指针
	ps->a = NULL;
	ps->capacity = ps->top = 0;
}
//销毁
void StackDestory(ST* ps)
{
	assert(ps);
	free(ps->a);//释放储存数据的空间
	ps->a = NULL;
	ps->capacity = ps->top = 0;
}

入栈、出栈

入栈的实现要比出栈复杂,主要是因为在进行数据入栈时,要检查栈的空间是否足够,如果不够则要申请新的空间,在C语言的实现中我们通常使用realloc函数(stdlib.h)实现,然后我们还要查验新申请空间的指向针针是否有问题,再置换指针和空间数据,存入数据


//入栈
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	//检查容量
	if (ps->capacity == ps->top)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		//ps->a指向需要重新分配内存的的内存块
        //newcapacity * sizeof(STDataType)是新空间的字节数
		STDataType* cur = (STDataType*)realloc(ps->a, newcapacity * sizeof(STDataType));
		//验证申请的空间有没有问题
		if (cur == NULL)
		{
			perror("realloc fail");
			exit(-1);//失败即退出程序
		}

		//还要把新指针给a,新空间给capacity
		ps->a = cur;
		ps->capacity = newcapacity;
	}

	ps->a[ps->top] = x;
	ps->top++;
}

出栈的结构相比于入栈可谓是十分简单了,可也有一些要注意的点:

  • 要验证栈中是否为空,如若为空,则无法进行出栈;
  • 这里出栈不需要释放空间; 
//获取数据都要检验,数据是否为空
//出栈
void StackPop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));//验证栈是否为空,如果为空,则无法出栈

	//不用释放空间
	//free(ps->a[ps->top]);
	ps->top--;
}

获取栈顶、获取栈顶对应号数

获取栈顶和出栈一样同样要验证栈中是否为空,同时返回栈顶对应数,这里就是ps->a[ps->top-1]

因为我的top是从0开始存的,所以按照数组的性质,要top-1

//获取栈顶
STDataType StackTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));//若无数据,无法获取栈顶

	return ps->a[ps->top-1];
}
//获取栈顶号数
int StackSize(ST* ps)
{
	assert(ps);

	return ps->top;
}

验空函数

通过封装一个独立的验空函数,就可以让多个函数同时应用,减少了代码的冗余,保持了代码的整洁。当然,验空所具有的作用也不可替代。

Tip:如果你已经提前定义了函数,在实现过程中即使放在最后完成也是可以的哦~

//验空
bool StackEmpty(ST* ps)
{
	assert(ps);

	return ps->top == 0;
}

3.结语 

看到这里,相信老铁们对如何用C语言实现栈已经有具体的认识。

我是计算机海洋的新进船长Captain_ldx,如果我的文章能对您有帮助的话,麻烦各位观众姥爷们点赞、收藏、关注,你们的每一次举手之劳都将化为船长的前进动力!

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值