数据结构——栈

1.1栈的概念及结构 

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

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

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

                                  特点:   后进后出(Last In First Out)

进栈出栈示意图::

1.2栈的实现

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

        观察以上三种结构,可以发现双向链表是比较复杂的,因为使用单链表进行头插就可以满足栈的实现,但是由于数组具有高效缓存的特点,因此栈的实现选择数组更好一点。

// 下面是定长的静态栈的结构,实际中一般不实用,所以我们主要实现下面的支持动态增长的栈
typedef int STDataType;
 #define N 10
 typedef struct Stack
 {
    STDataType _a[N];
    int _top; // 栈顶
}Stack;
 
// 支持动态增长的栈
typedef int STDataType;
 typedef struct Stack
 {
    STDataType* _a;
    int _top;       // 栈顶
    int _capacity;  // 容量 
}Stack;
 // 初始化栈 
void StackInit(Stack* ps); 
// 入栈 
void StackPush(Stack* ps, STDataType data); 
// 出栈 
void StackPop(Stack* ps); 
// 获取栈顶元素 
STDataType StackTop(Stack* ps); 
// 获取栈中有效元素个数 
int StackSize(Stack* ps); 
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps); 
// 销毁栈 
void StackDestroy(Stack* ps); 

接下来将一一演示代码的实现

以vs2022进行演示,先是创建了 Stack.h  Stack.c  和  test.c  一个头文件和两个  .c 文件

//包含的头文件有
#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;

由于静态栈使用较少,所以用动态栈展示。 

1.2.1 栈的初始化

//Stack.h
//初始化
void STInit(ST* pst);


//Stack.c
//初始化
void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->capacity = pst->top = 0;
}


 

进行调试发现,栈初始化成功。

后续操作与初始化一致,所以就单独将  Stack.c  里面代码展示。 

1.2.2 栈的销毁

//销毁
void STDestory(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->capacity = pst->top = 0;
}

1.2.3 入栈

void STPush(ST* pst, STDataType x)
{
	assert(pst);
	//判断空间够不够
	if (pst->capacity == pst->top)
	{
		//空间不够,需要申请一片空间
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
		if (tmp == NULL)
		{
			perror("mealloc fail!");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}

因为栈的定义就已经限制了栈只可以一端进栈,所以就不用区分头插和尾插,

1.2.4 删除元素

 

//删除
void STPop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
	pst->top--;
}

删除元素时,要注意不仅栈的地址不能为空,并且里面的元素也不可以为空。

1.2.5 判空

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

	return pst->top == 0;
}

如果 pst->top == 0,就为真 

1.2.6 获取栈顶元素

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

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

1.2.7 获取元素个数

int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}

1.3 栈打印

       是不是看了以上代码演示,觉得为什么会有一个bool类型呢?接下来就将为大家展示一下bool这个判空函数的使用方法。

#define _CRT_SECURE_NO_WARNINGS 1

#include"Stack.h"


int main()
{
	ST st;
	STInit(&st);
	STPush(&st, 1);
	STPush(&st, 2);
	STPush(&st, 3);
	STPush(&st, 4);
	while (!STEmpty(&st))
	{
		printf("%d ", STTop(&st));
		STPop(&st);
	}
	printf("\n");
	STDestory(&st);
	return 0;
}

以上就是栈的基本内容以及操作了,下一期将为大家带来队列的内容。 

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值