C语言——模拟实现栈

先讲一讲栈的特性,将数据压入栈中,先放进栈中的数据后取出来,后放进栈中的数据先被取出来,也就是“先进后出,后进先出”。

C语言模拟实现栈可以用顺序表,单链表,双链表,那么用哪一种是最好的?

实现数据的添加和删除,如果用单链表,添加数据需要先找到尾,遍历链表,然后再添加,这样就消耗了时间,时间复杂度是O(n),同样,删除的话也需要先遍历链表,在删除.当然,如果你将第一个结点作栈顶,最后以一个结点作栈底,这样就是头插头删,时间复杂度是O(1),也就消除了这个最大的影响。

如果用双链表,的确可以解决单链表中的问题,但是相比较于顺序表而言,空间会有较大的开销,而单链表相对于顺序表,单链表开辟的空间会更大,最好还是做到能省则省,因此,综合考虑,还是使用顺序表更优。

在头文件中包含以下数据库中的头文件,将栈的数据类型重命名为STDataType

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


#define START 4

typedef int STDataType;

在这个栈中有数据的数组,有当前顺序表中有效的数据的个数,还有顺序表的最大容量,将这个栈的结构体重命名为Stack。

typedef struct Stack
{
	STDataType* data;
	int top;
	int capacity;
}Stack;

再“Stack.h”中声明一下函数,在这里我讲一下栈的初始化、销毁、入栈、出栈、判断栈的容量、取栈顶数据、计算栈的有效数据个数以及判断栈是否为空。

//声明函数

//初始化栈
void InitStack(Stack* ps);

//销毁栈
void DestoryStack(Stack* ps);

//添加数据到栈——入栈
void StackPush(Stack* ps, STDataType x);

//判断栈是否已满
void CheckStack(Stack* ps);

//从栈顶删除数据——出栈
void StackPop(Stack* ps);

//取出栈顶数据
STDataType StackTop(Stack* ps);

//计算栈中有多少个数据
int StackSize(Stack* ps);

//判断栈是否为空
bool StackEmpty(Stack* ps);

1.初始化栈

//初始化栈
void InitStack(Stack* ps)
{
	assert(ps);

	ps->data = (STDataType*)malloc(sizeof(STDataType) * START);
	if (ps->data == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}

	ps->capacity = START;
	ps->top = 0;//表示在栈顶的上面
}

 栈一开始的容量可以自定义,我在头文件使用宏定义,将初始容量定义为START,如果空间开辟失败就打印失败了,并且中止程序,毕竟如果连空间都开辟不成功,还怎么完成后续操作。

ps->top=0既表示当前栈中的有效数据个数,也表示如果添加数据,那么top就在栈顶数据的上方,当然,ps->top=-1也是可以的,这样栈顶数据和top的高度就一样。

2.销毁栈

//销毁栈
void DestoryStack(Stack* ps)
{
	assert(ps);

	free(ps->data);
	ps->data = NULL;
	ps->capacity = ps->top = 0;
}

这里就没什么好讲的,销毁栈就将开辟的空间还给电脑,再将capacity和top都置为0。 

3.判断栈是否已满

//判断栈是否已满
void CheckStack(Stack* ps)
{
	if (ps->capacity == ps->top)
	{
		STDataType* ptr = realloc(ps->data, sizeof(STDataType) * ps->capaciy * 2);
		if (ptr == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}

		ps->data = ptr;
		ps->capacity *= 2;
	}
}

 如果栈已经满了,就将它的内存开辟到原来的两倍,使用realloc,如果后面空间足够的话就直接增容,如果空间不够的话就额外再开辟一块内存,如果不为空就将这块空间的地址给ps->data,然后再将容量乘以2。开辟三倍也是可以的,但是最合适的还是开辟到原来的两倍。

4.入栈

//添加数据到栈——入栈
void StackPush(Stack* ps, STDataType x)
{
	assert(ps);

	CheckStack(ps);

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

每次添加数据到栈中都要确认一下栈是否已经满了,调用CheckStack函数。入栈是将数据插入到顺序表的最后面,再将top++。 

5.出栈

//从栈顶删除数据——出栈
void StackPop(Stack* ps)
{
	assert(ps);
	assert(ps->top != 0);

	ps->top--;
}

出栈的话要断言一下,如果栈中什么都没有那还删除什么。出栈很简单,就是将top--,有的人会将栈顶的数据重置为0,这其实是没有意义的,如果栈的类型不是int,而是double,char,或者是结构体,置为0就显得不合适,随意不必在此多此一举。 

 6.取栈顶数据

//取出栈顶数据
STDataType StackTop(Stack* ps)
{
	assert(ps);
	assert(ps->top != 0);

	return ps->data[ps->top - 1];
}

与删除栈顶数据一样,也要断言栈不能为空,因为ps->top表示栈中的有效数据个数,所以栈顶元素的下标就是ps->top-1,因为再头文件中将int重命名为STDataType,所以函数的返回值也要是这个,保证数据类型相同

7.计算栈中有效数据个数

//计算栈中有多少个数据
int StackSize(Stack* ps)
{
	assert(ps);

	return ps->top;
}

直接返回ps->top即可

8.判断栈是否为空

//判断栈是否为空
bool StackEmpty(Stack* ps)
{
	assert(ps);

	return ps->top == 0;
}

 函数返回类型是bool,如果ps->top==0,就是真,返回true,反之就返回false

接下来就调用一下这些函数

void TestStack()
{
	Stack st;

	InitStack(&st);

	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);
	StackPush(&st, 4);

	while (!StackEmpty(&st))
	{
		printf("%d ", StackTop(&st));
		StackPop(&st);
	}
	printf("\n");

    DestoryStack(&st);
}

初始化栈后先将一些元素入栈,在依次打印,记住要销毁栈,防止内存泄漏

因为栈的性质就是“先入后出,后进先出”,所以就是打印“4,3,2,1”。打印栈中的数据不是遍历它,而是判断栈是否为空,不为空就打印栈顶数据,然后在删除它,直到栈为空。

void TestStack()
{
	Stack st;

	InitStack(&st);

	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);

	StackPop(&st);
	StackPop(&st);
	StackPop(&st);
	StackPop(&st);

	DestoryStack(&st);
}

 如果栈中没有数据还删除的话就会报错,这就是断言的好处。

void TestStack()
{
	Stack st;

	InitStack(&st);

	printf("%d\n", StackSize(&st));
	StackPush(&st, 1);
	StackPush(&st, 2);

	printf("%d ", StackTop(&st));
	StackPop(&st);

	StackPush(&st, 3);
	printf("%d\n", StackSize(&st));


	StackPush(&st, 4);
	StackPush(&st, 5);

	printf("%d ", StackTop(&st));
	StackPop(&st);
	printf("%d ", StackTop(&st));
	StackPop(&st);

	StackPush(&st, 6);
	StackPush(&st, 7);
	while (!StackEmpty(&st))
	{
		printf("%d ", StackTop(&st));
		StackPop(&st);
	}
	printf("\n");

	DestoryStack(&st);
}

 如果在添加完数据就打印,就需要将栈顶数据删除,这样依旧保持栈的性质

栈中一开始没有数据,所以就打印“0”,添加数据“1,2”,后栈顶数据是“2”,打印并删除它, 再将“3”入栈,这样栈中的数据就有两个,打印StackSize。

以上就是本次介绍的使用C语言模拟实现栈。 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值