数据结构——栈(C语言实现)

什么是栈?

栈的概念

栈是一种特殊的线性数据结结构,栈只能允许对数据在固定的一端进行插入操作和删除操作。插入数据和删除数据的一端是栈顶,而另一端就是栈底。栈的性质就是数据后进先出,即LIFO原则(last in first out)。当有一列整数{1,2,3,4,5},依次让这些数入栈,出栈的顺序有多种。如1,2,3,4,5,这种情况就是进一个出一个的情况,而5,4,3,2,1就是依次入栈依次出栈的顺序。当然,2,5,4,3,1这种出栈顺序也是合法的。因为栈的出栈要讲究后进先出

栈的结构

栈的结构类似于一个弹夹,数据入栈操作就类似于子弹压进弹夹一样,先压的子弹就在弹夹的底部。而数据出栈操作就类似开火,后压进去的子弹在弹夹的顶部,所以,先被打出去的子弹也就是弹夹顶部的子弹。可以将栈对数据操作理解成弹弹夹对子弹的操作。

数据结构——栈(C语言实现)_第1张图片

栈的实现

栈的实现方式

栈的实现方式分为两种,分别是数组栈实现和链式栈的实现。
数据结构——栈(C语言实现)_第2张图片
从图上结构不难发现,相对链式栈而言,数组栈的插入和删除数据的代价较小,所以,通常栈的实现采用的是数组栈的结构。本篇文章也是对数组栈的方式进行讲解。

栈的定义

本篇文章实现的是动态增长的数组栈,相信掌握了这一种经典的结构后,其他的结构的实现对你来说也是小菜一碟。话不多说直接上菜!首先,我们需要定义一个指针来指向动态开辟内存的地址。其次就是用一个记录栈顶位置,最后就是定义一个变量来记录动态开辟内存的容量,容量如果满了,我们就对动态申请的内存进行扩容。

//重命名数据类型
//方便根据实际需求进行更改
typedef int STDataType;

typedef struct Stack
{
	//通过数组形式存储数据
	STDataType* data;
	//记录栈顶
	int top;
	//数组容量
	int capacity;
}ST;

接口的介绍

//初始化栈
void StackInit(ST* ps);

//销毁栈
void StackDestroy(ST* ps);

//数据入栈
void StackPush(ST* ps, STDataType x);

//空栈判断
bool StackEmpty(ST* ps);

//数据出栈
void StackPop(ST* ps);

//栈的有效元素个数
int StackSize(ST* ps);

//获取栈顶元素
STDataType StackTop(ST* ps);

初始化栈的实现

首先我们需要对形参进行判断,然后动态申请一块连续的空间存放数据。初始容量为4。记录栈顶的位置的变量初始化成0。
数据结构——栈(C语言实现)_第3张图片

//初始化栈
void StackInit(ST* ps)
{
	//断言判断指针有效性
	assert(ps);

	//初始化
	//动态申请内存
	STDataType* tmp = (STDataType*)malloc(sizeof(STDataType) * 4);
	
	//判断动态内存是否申请成功
	if (NULL == tmp)
	{
		perror("malloc fail\n");
		return;
	}
	
	//初始化栈
	ps->data = tmp;
	ps->capacity = 4;
	ps->top = 0;

}

销毁栈的实现

将动态内存释放并手动置空,将capacity和top置0。
数据结构——栈(C语言实现)_第4张图片

//销毁栈
void StackDestroy(ST* ps)
{
	assert(ps);

	//释放动态内存
	free(ps->data);
	ps->data = NULL;
	
	//置0
	ps->top = ps->capacity = 0;

}

数据入栈的实现

首先,判断动态申请的数组容量是否满了,满了的话就扩容。然后,插入数据。最后,移动top变量的位置,使其指向下一个数据入栈的位置。
数据结构——栈(C语言实现)_第5张图片

//数据入栈
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	
	//判断数组容量,满了就扩容
	if (ps->top == ps->capacity)
	{
		//使用临时变量保存扩容后的地址,避免异地扩容出现问题
		STDataType* tmp = (STDataType*)realloc(ps->data, sizeof(STDataType) * ps->capacity * 2);
		if (tmp == NULL)
		{
			perror("realloc fail\n");
			return;
		}
		ps->data = tmp;
		//调整数组容量
		ps->capacity *= 2;
	}

	//压栈
	ps->data[ps->top] = x;

	//top指向栈顶
	ps->top++;

	//写成下面这种也可以
	//ps->data[ps->top++] = x;
}

判断栈是否为空

若控制下一个数据入栈的位置变量指向0时,表示当前栈没有数据。
数据结构——栈(C语言实现)_第6张图片

//空栈判断
bool StackEmpty(ST* ps)
{
	assert(ps);

	//若栈顶指向0表示空栈
	return ps->top == 0;
}

数据出栈的实现

通过将控制数据进栈位置的变量-1,使下一次数据进栈覆盖原数据达到数据出栈的效果。需要注意当栈为空时无法出数据。
数据结构——栈(C语言实现)_第7张图片

//数据出栈
void StackPop(ST* ps)
{
	assert(ps);

	//空栈不可删除数据
	assert(!StackEmpty(ps));
	
	//出栈
	ps->top--;

}

栈有效数据的个数

栈有效数据的个数其实就是当前控制数据进栈位置变量的值。
数据结构——栈(C语言实现)_第8张图片

//栈有效元素个数
int StackSize(ST* ps)
{
	assert(ps);

	return ps->top;

}

获取栈顶元素

就是取数组中下标为有效个数-1位置处的元素。需要注意的是空栈不能取栈顶元素。
数据结构——栈(C语言实现)_第9张图片

//栈顶元素
STDataType StackTop(ST* ps)
{
	assert(ps);
	
	//避免空栈越界访问
	assert(!StackEmpty(ps));
	
	return ps->data[ps->top - 1];

}

你可能感兴趣的:(数据结构,c语言,算法)