【数据结构之C语言实现栈】

1.栈 的 概 念 与 结 构

栈:                                                                                             

        一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据的插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守LIFO(先进后出后进先出的原则)。

压 栈:

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

出 栈:

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

栈 底 层 结 构 选 型

       栈的实现一般可以使用数组或者链表的实现,相对而言数组的结构实现更优一些。因为数组在尾插上插入数据的代价比较小。

2.栈的实现

 依据前面数据结构的实现,在实现栈时,我们也需要三个文件。Stack.h(栈结构的定义以及函数的声明),Stack.c(函数功能的实现),test.c(函数功能的测试)。

2.1 Stack.h(栈结构的定义以及函数的声明)

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
// 栈结构的定义以及函数功能的实现   先进后出
// 
//栈的结构的定义  用数组实现的时候时间复杂度较小,操作较为简单 。空间复杂度小
//缓存命中--数组(内存存储时连续)
typedef int STDatatype;
typedef struct Stack
{
	STDatatype * arr;
	int top;
	int capacity;
}ST;

//函数的声明
//初始化
void STInit(ST* ps);

//销毁
void STDestroy(ST* ps);

//入栈
void STPush(ST* ps, STDatatype x);

//判断栈是否为空
bool STEmptty(ST* ps);

//出栈
void  STPop(ST* ps);

//获取栈顶元素
STDatatype STTop(ST* ps);

//获取栈的数据元素的个数
int STSize(ST* ps);

2.2 Stack.c(函数功能的实现)

#include "Stack.h"
2.2.1 初始化
//初始化
void STInit(ST* ps)
{
	assert(ps);
	ps->arr = NULL;
	ps->top = ps->capacity = 0;
}

《实现思路》

       先判断所传地址的有效性,再对指向数组的指针置为空,将top(也可以标记栈中数据的个数)和capacity(栈的空间大小)都置为0。

2.2.2 销毁
//销毁
void STDestroy(ST* ps)
{
	assert(ps);
	if (ps->arr)
		free(ps->arr);
	ps->arr = NULL;
	ps->top = ps->capacity = 0;
}

《实现思路》

       先判断所传地址的有效性,如果指向数组的指针非空,则需要将动态申请的空间释放掉,并将其置为空。再top和capacity都置为0。

2.2.3 入栈
//入栈
void STPush(ST* ps, STDatatype x)
{
	assert(ps);
	//先判断空间够不够,空间不够就需要动态增容
	if (ps->top == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDatatype* temp = (STDatatype*)realloc(ps->arr, newcapacity * sizeof(STDatatype));
		if (temp == NULL)
		{
			perror("realloc fail");
			exit(1);
		}
		ps->arr = temp;
		ps->capacity = newcapacity;
	}
	ps->arr[ps->top++] = x;
}

《实现思路》

          先判断所传地址的有效性,再判断空间是否够(和前面的顺序表的空间大小判断一样,都是以二倍扩容)。最后通过指向数组的指针再下标为top的位置插入数据即可,除此之外top++。

2.2.4  判断栈是否为空
//判断栈是否为空
bool STEmptty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}

《实现思路》

          先判断所传地址的有效性,对于判空只需要直接返回top为0即可,因为top不仅是标记当前栈顶的位置,也表示当前栈中的元素个数。

2.2.5 出栈
//出栈
void  STPop(ST* ps)
{
	assert(ps);
	assert(!STEmptty(ps));
	ps->top--;
}

《实现思路》

          先判断所传地址的有效性,再进行判断栈是否为空,如果为空,就不能进行出栈操作。反之,栈不为空时,出栈只需要top--即可。

2.2.6 获取栈顶数据
//获取栈顶元素
STDatatype STTop(ST* ps)
{
	assert(ps);
	assert(!STEmptty(ps));
	return ps->arr[ps->top - 1];
}

《实现思路》

            先判断所传地址的有效性,再进行判断栈是否为空,如果为空,就不能进行获取栈顶数据的操作。反之,栈不为空时,只需要通过指向数组的指针访问top-1位置的元素。因为top标示的是当前栈的数据个数,它是和栈顶数据的下标相差1的,并不相同。

2.2.7 获取栈中的数据个数
//获取栈的数据元素的个数
int STSize(ST* ps)
{
	assert(ps);
	return ps->top;
}

《实现思路》

           先判断所传地址的有效性,再直接返回top的值即可。

 2.3 test.c(函数功能的测试)

#include "Stack.h"

//栈数据结构函数功能的测试部分
void STprint(ST* st)
{
	while (!STEmptty(st))
	{
		printf("%d ", STTop(st));
		STPop(st);
	}
	printf("\n");
}
void test()
{
	ST st;
	STInit(&st);
	STPush(&st, 1);
	STPush(&st, 2);
	STPush(&st, 3);
	STPush(&st, 4);
	printf("size:%d\n", STSize(&st));
	STprint(&st);
	printf("now size:%d\n", STSize(&st));
	STDestroy(&st);
}
int main()
{
	test();
	return 0;
}

如有错误,还望指正!!!

关注博主,优质内容不断更新!!!

  • 21
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小峰编程

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

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

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

打赏作者

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

抵扣说明:

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

余额充值