c语言模拟实现栈(动图演示)

栈的定义

栈是允许在同一端进行插入和删除操作的特殊线性表 。允许进行插入和删除操作的一端称为栈顶 (top),另一端为栈底 (bottom);栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。特点是:先进后出,后进先出。

栈的接口

首先我们先来看将使用3个数据{2,3,4}形成栈的示意图:
请添加图片描述

元素定义

由定义可知,栈是线性表,可以分为顺序存储结构(顺序表)和链式存储结构(链表)来实现,下面我们用数组来实现,即实现它的顺序存储结构,其次我们知道他是可以获取堆顶元素的,所以我们还需要一个top指针记录栈顶的位置(这个不是真正意义上的指针,而是记录栈顶元素的位置),且因为我们是动态开辟实现栈,所以我们还需要一个capacity来记录当前的元素个数(相当于size),以检查是否需要进行扩容
定义如下:

typedef int Datatype;    //此处是为了方便栈存放不同的元素类型

typedef struct Stack {
	Datatype* a;        //管理数组
	int top;//栈顶元素下标
	int capacity;//记录当前容量大小
}Stack;

初始化

栈的初始化就较为简单了,将a置空(相当于初始化),top和capacity=0,
即可
代码实现如下:

//初始化函数
void InitStack(Stack* st)
{
	assert(st);

	st->a = NULL;
	st->capacity = 0;
	st->top = -1;   //指向栈顶元素
}

这里的top=-1,表示的状态是数组中没有元素,因为有元素的话,比如说如果数组中有一个元素,top就等于0,即数组第一个元素的下标位置

数据入栈

数据入栈的操作就是,将新值插入到数组末尾,然后更新top和capacity,
代码如下:

//入栈
void Push(Stack* st,Datatype x)
{
	assert(st);
	if (st->capacity == (st->top + 1))
	{
		int newcapacity = st->capacity == 0 ? 4 : 2 * st->capacity;
		Datatype* tmp = (Datatype*)realloc(st->a,sizeof(Datatype) * newcapacity);
		if (tmp == NULL)   //开辟失败,tmp会指向空
		{
			printf("realloc failed\n");
			exit(-1);//终止程序
		}

		st->a = tmp;
		st->capacity = newcapacity;
	}

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

数据出栈

数据出栈实现也很简单,我们直接逻辑删除,就是将capacity–,元素的值其实还在数组中,只是我们假装看不见 😐 ,但简单是简单这里还是有坑点的,就是我们删除数据的时候,如果栈已经空了,我们还进行删除操作,就会影响后续的使用,所以我们每次都要先判断栈是否为空
代码实现如下:

//出栈
void Pop(Stack* st)
{
	assert(st);
	if (!empty(st))
	{
		--st->top;
	}

}

获取栈顶元素

这里提一下,我们函数实现时判断一些空指针或者不可进行操作的情况时,例如:下面当栈为空时还去获取栈顶元素。这些情况的判断最好都用assert去判断,因为当我们代码行数多起来时,那个接口出了问题,会马上被显示出来还有行号。
例:
如果栈中没有数据,而我们还去获取栈顶元素,他不仅会报错而且还会告诉我们哪个位置出的错
请添加图片描述
代码实现:

 //拿到栈顶元素
Datatype top(Stack* st)
{
	assert(st);
	//if (!empty(st))//此处也可用assert
	//{
	//	return st->a[st->top];
	//}
	assert(!empty(st));
	return st->a[st->top];
}

是否为空

这里注意如果要使用c++中的bool类型,要印=引头文件<stdbool.h>

//检查是否为空
bool empty(Stack* st)
{
	assert(st);

	return st->top == -1;//为0即为空 为真true
}

销毁栈

销毁栈的操作其实就是在初始化的基础上,将我们数据入栈时,为我们的数组管家a动态开辟的内存空间释放掉,这里如果单纯置空而不进行释放操作,会造成内存泄漏

//销毁栈
void Destroy(Stack* st)
{
	assert(st);
	free(st->a);
	st->a = NULL;
	st->capacity = 0;
	st->top = -1;
}

完整代码


//初始化函数
void InitStack(Stack* st)
{
	assert(st);

	st->a = NULL;
	st->capacity = 0;
	st->top = -1;//指向栈顶元素
}
//入栈
void Push(Stack* st,Datatype x)
{
	assert(st);
	if (st->capacity == (st->top + 1))
	{
		int newcapacity = st->capacity == 0 ? 4 : 2 * st->capacity;
		Datatype* tmp = (Datatype*)realloc(st->a,sizeof(Datatype) * newcapacity);
		if (tmp == NULL)
		{
			printf("realloc failed\n");
			exit(-1);//终止程序
		}

		st->a = tmp;
		st->capacity = newcapacity;
	}

		st->a[++st->top] = x;
}
//出栈
void Pop(Stack* st)
{
	assert(st);
	if (!empty(st))
	{
		--st->top;
	}

}
//检查是否为空
bool empty(Stack* st)
{
	assert(st);

	return st->top == -1;//为0即为空 为真true
}
//拿到栈顶元素
Datatype top(Stack* st)
{
	assert(st);
	//if (!empty(st))//此处也可用assert
	//{
	//	return st->a[st->top];
	//}
	assert(!empty(st));
	return st->a[st->top];
}
//销毁栈
void Destroy(Stack* st)
{
	assert(st);
	free(st->a);
	st->a = NULL;
	st->capacity = 0;
	st->top = -1;
}

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值