【数据结构】格洛克怎么上膛?栈的结构帮你解答!

目录

1.摘要
2.引子
3.什么是栈?
4.栈的代码实现
    4.1.用顺序表实现栈
    4.2.头文件
    4.3.接口文件
    4.4.测试文件
5.参考文献

1.摘要

本文主要介绍栈的结构以及栈的代码实现。

2.引子

相必在座的军迷朋友一定不少吧,哈哈,实不相瞒,我也是一个轻武器的铁杆军迷。

如果提到手枪,那么不得不提的就是格洛克了。简洁的外观搭配强大的火力,在军用民用市场广受追捧。

那么大家是否见过往弹匣压子弹呢?对了对了,就是一发一发地把子弹压入弹仓

在这里插入图片描述



不对啊不对啊,我们今天不是来研究栈这个数据结构的吗?怎么扯得这么远了?
别急别急,待会你就知道为什么要讲这个例子了。

3.什么是栈?

和之前讲的顺序表和链表一样,栈也是线性表的一种,只不过,栈遵循的规则比起顺序表、链表来严格了一点

让我们给出栈的定义:栈是满足后进先出(Last in First out,LIFO)规则的线性表,只允许在固定的一端进行插入和删除操作。进行插入删除操作的一端叫做栈顶,另一端叫做栈底。

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

下图清楚地展示了什么是入栈/出栈:

在这里插入图片描述
入栈和出栈:

在这里插入图片描述
在这里插入图片描述
多组数据的入栈和出栈:

在这里插入图片描述

当然了,顺便提一句,压栈操作的英文是Push,出栈操作的英文是Pop

只要牢牢记住后进先出的原则,即第一个进栈的数据最后一个才能出来,那么栈的性质就十分通透了。

还记得之前的给弹匣压弹吗?有没有一点感觉呢现在?
对了,第一发压进去的子弹最后才能射出来,最后压进去的子弹第一发就能射出来!这难道不是后进先出吗?

回顾一下开篇的那张压子弹图片,这难道不是压栈操作吗:

在这里插入图片描述

再来看一看子弹上膛的情景,这难道不是出栈操作吗:

在这里插入图片描述

后进先出!后进先出!后进先出!重要的事情说三遍!

4.栈的代码实现

4.1.用顺序表实现栈

由于栈是一类特殊的线性表,所以栈既可以用顺序表实现,也可以用链表来实现。

经过考虑,由于栈的操作通常是在栈顶完成,而通常线性表头我们认为是栈底,而线性表尾我们认为是栈顶,所以为了方便在线性表尾进行操作,本次我们采用动态开辟数组的方式来实现栈,尾部操作的时间复杂度华仅为O(1)。

当然,如果使用双向链表,也是很方便的,但是非循环单链表进行尾部操作需要遍历,时间复杂度华为O(N),不是很划算。

4.2.头文件

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

# define INIT_NUM 4
typedef int StackDataType;
typedef struct Stack {
	StackDataType* data;
	size_t size;
	size_t capacity;
}Stack;


void StackInit(Stack* ps);
void StackDestroy(Stack* ps);
void StackPush(Stack* ps, StackDataType x);
void StackPop(Stack* ps);
int StackEmpty(Stack* ps);
size_t StackSize(const Stack* ps);
StackDataType StackTop(const Stack* ps);

4.3.接口文件

我们尤其强调以下四个接口:

// 1.压栈
void StackPush(Stack* ps, StackDataType x);

// 2.出栈
void StackPop(Stack* ps);

// 3.判空,栈为空返回1,非空返回0
int StackEmpty(Stack* ps);

//取栈顶元素
StackDataType StackTop(const Stack* ps);

以下是接口文件的实现:

void StackBuy(Stack* ps)
{
	assert(ps);
	ps->capacity = ps->capacity == 0 ? INIT_NUM : 2 * ps->capacity;
	
	StackDataType* tmp = (StackDataType*)realloc(ps->data, ps->capacity * sizeof(StackDataType));
	if (tmp == NULL)
	{
		printf("realloc failed\n");
		return;
	}
	ps->data = tmp;
}

void StackCheck(Stack* ps)
{
	assert(ps);
	if (ps->capacity == ps->size)
	{
		StackBuy(ps);
	}
}
void StackInit(Stack* ps)
{
	assert(ps);
	ps->capacity = 0;
	ps->size = 0;
	ps->data = NULL;
	StackBuy(ps);
}

void StackDestroy(Stack* ps)
{
	assert(ps);
	ps->capacity = 0;
	ps->size = 0;
	free(ps->data);
	ps->data = NULL;
}

void StackPush(Stack* ps, StackDataType x)
{
	assert(ps);
	StackCheck(ps);
	ps->data[ps->size] = x;
	ps->size++;
}

void StackPrint(const Stack* ps)
{
	assert(ps);
	int i = 0;
	for (i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->data[i]);
	}
	printf("\n");
}

void StackPop(Stack* ps)
{
	assert(ps);
	if (ps->size == 0)
		return;
	else
		--ps->size;
}

int StackEmpty(Stack* ps)
{
	return ps->size == 0;
}

size_t StackSize(const Stack* ps)
{
	return ps->size;
}

StackDataType StackTop(const Stack* ps)
{
	assert(ps);
	assert(StackEmpty(ps));
	return ps->data[ps->size - 1];
}

4.4.测试文件

Test1()
{
	Stack st;
	Stack* pstack = &st;
	StackInit(pstack);


	StackPush(pstack, 1);

	StackPush(pstack, 2);

	StackPush(pstack, 3);

	StackPush(pstack, 4);

	StackPop(pstack);
	StackPop(pstack);

	StackPop(pstack);

	StackPop(pstack);



	printf("%d\n", StackEmpty(pstack));
	printf("%d\n", StackSize(pstack));

	StackDestroy(pstack);
	
}
int main()
{
	Test1();
	return 0;
}

5.参考文献

1.压栈
2.出栈

  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 23
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

DanteIoVeYou

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

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

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

打赏作者

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

抵扣说明:

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

余额充值