一.栈的概念与结构

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

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。

在这里插入图片描述

在这里插入图片描述

二.顺序栈与链栈

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上
插入数据的代价比较小。那是为什么?且听下文分解。

1.顺序栈

在这里插入图片描述

2.链栈

1.单链表栈

在这里插入图片描述

将栈顶与栈低换个位置可以解决该问题,如下图:

在这里插入图片描述

2.双链表栈

在这里插入图片描述

  1. 由于双向链表比单链表多一个指针,基于节省内存的原由单链表优于双向链表。
  2. 数组的效率更优于单链表,原因:链表每一次插入一个数据都要申请一个节点,每次删除一个数据都要释放一个节点,且顺序栈包含数据+容量+栈顶,而链栈包含数据+指针,每个数据都要包含指针,顺序栈较于连栈会省一些内存。

接下来我将实现最优的——>顺序栈

三.顺序栈的实现

会写顺序表,那么实现顺序栈会非常轻松,这里就不一一介绍了,直接上代码。

1.创建顺序栈

typedef int STDataType;

typedef struct Stack
{
	STDataType* arr; //栈空间的首地址
	int top;         //栈顶
	int capacity;    //容量
}ST;

ST st;//st代表顺序栈

2.栈的初始化

void STInit(ST* pst)
{
	assert(pst);

	pst->a = NULL;
	pst->capacity = pst->top = 0;
}

3.入栈

void STPush(ST* pst, STDataType x)
{
	assert(pst);

	//栈满
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;
		STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}

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

4.出栈

void STPop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);

	pst->top--;
}

5.获取栈顶元素

STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);

	return pst->a[pst->top - 1];
}

6.栈的大小

int STSize(ST* pst)
{
	assert(pst);

	return pst->top;
}

7.栈的判空

bool STEmpty(ST* pst)
{
	assert(pst);

	return pst->top == 0;
}

8.栈的销毁

void STDestory(ST* pst)
{
	assert(pst);

	free(pst->a);
	pst->a = NULL;
	pst->capacity = pst->top = 0;
}

四.栈的盲区

由于栈的特殊结构,只能遵循后进先出的原则,不允许随便遍历栈,否则就失去了栈的特点,只能用以下的代码得到数据:

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

五.模块化源代码

1.Stack.h

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

typedef int STDataType;

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

//初始化和销毁
void STInit(ST* pst);
void STDestory(ST* pst);

//入栈和出栈
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);

//获取栈顶数据
STDataType STTop(ST* pst);

//判空
bool STEmpty(ST* pst);

//获取栈中的数据个数
int STSize(ST* pst);

2.Stack.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"Stack.h"

void STInit(ST* pst)
{
	assert(pst);

	pst->a = NULL;
	pst->capacity = pst->top = 0;
}

void STDestory(ST* pst)
{
	assert(pst);

	free(pst->a);
	pst->a = NULL;
	pst->capacity = pst->top = 0;
}

void STPush(ST* pst, STDataType x)
{
	assert(pst);

	//栈满
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;
		STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}

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

void STPop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);

	pst->top--;
}

STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);

	return pst->a[pst->top - 1];
}

bool STEmpty(ST* pst)
{
	assert(pst);

	return pst->top == 0;
}

int STSize(ST* pst)
{
	assert(pst);

	return pst->top;
}

更多推荐