数据结构-栈

大家好,今天带来的是关于数据结构初阶中的栈和队列的内容,一起来看看吧!!!

1.栈的概念

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

类比:只有一端开口的羽毛球桶

2.栈的实现

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

2.1初始化和销毁

初始化的一个难题就是top的赋值问题,以及对应的哪种情况。

分两种情况,采用假设法+画图,很快就能理解!

1.top=-1,假设入栈一个数据1后,top++,此刻top=0,栈顶数据为1,在数组中a[0]表示数组首元素,即top指向栈顶数据。

2.top=0,假设入栈一个数据1后,top++,此刻top=1,栈顶数据为a[0], a[1]表示数组第二个数据,即top指向栈顶数据的下一个数据。

考虑到我想用top代表有效数据个数,因此我这里用的是方法2,令ps->top=0,top指向的是栈顶数据的下一个数据,也同时代表了栈内数据个数。


2.2入栈

之前我们学习了有关顺序表的知识,这里的代码理解起来就很容易了。

插入数据之前,要判断当前内存是否足够,若不够,要扩容。

2.3出栈

出栈就是删除元素,因为栈内数据只能从栈顶入,栈顶出。所以,出栈一次,只用删除一次栈顶数据即可。

2.4获取栈顶元素

之前初始化根据我的赋值是:top=0;因此top指向的是栈顶元素的下一个数据。那么要获取栈顶元素,就是获取top的前一个元素,也就是ps->a[top-1].

2.5获取栈有效元素个数

之前根据初始化赋值我的设置,令top=0,因此top也恰好代表了栈中的有效数据个数。

故直接返回ps->top即可。

2.6判空

复制代码
当栈为空时,表示栈中没有任何元素。当栈非空时,表示栈中至少有一个元素。
因此只需要判断栈中有效数据个数是否不为0即可。
这里1 0 我们想到了用bool函数来表示。

3.总结

写到这里,我们就实现了一个栈,有了前面顺序表的基础,是不是感觉代码写起来还是比较简单的。这里给出总代码。

3.1 test.c

cpp 复制代码
//test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
#include"Stack.h"

int main()
{
	ST ps;

	STInit(&ps);
	STPush(&ps, 1);
	STPush(&ps, 2);
	STPush(&ps, 3);
	STPush(&ps, 4);
	//printf("%d\n",STTop(&ps));
	
	//访问栈中所有元素
	while (!STEmpty(&ps))
	{
		printf("%d ", STTop(&ps));
		STPop(&ps);
	}

	STDestroy(&ps);
	return 0;
}

3.2 Stack.c

cpp 复制代码
//Stack.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"

//初始化 
void STInit(ST* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->capacity = 0;

	ps->top = 0;//top指向栈顶的下一个数据,可画图理解

	//ps->top=-1;//top指向栈顶数据,画图理解
}


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


//入栈
void STPush(ST* ps, STDataType x)
{
	assert(ps);
	//插入之前判断内存够不够
	if (ps->top == ps->capacity)
	{
		//扩容
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		STDataType* tmp =(STDataType*) realloc(ps->a, newcapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}

	//插入数据
	ps->a[ps->top]=x;//根据初始化阶段,我这里的top指向的是栈顶数据的下一个数据,因此直接插入数据即可
	ps->top++;
}

//出栈
void STPop(ST* ps)
{
	assert(ps);
	ps->top--;
}

//获取栈顶元素
STDataType STTop(ST* ps)
{
	assert(ps);
	assert(ps->top > 0);

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

//获取栈中有效数据个数
int STSize(ST* ps)
{
	assert(ps);

	return ps->top - 1;
}

//判空
bool STEmpty(ST* ps)
{
	assert(ps);

	return ps->top == 0;
	//等价于
	/*if(ps->top==0)
	{
		return true;
	}
	else
	{
		return false;
	}*/
}

3.3 Stack.h

cpp 复制代码
//Stack.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>

//定义一个动态的栈
typedef int STDataType;

typedef struct Stack
{
	STDataType* a;
	int top;//栈顶
	int capacity;//容量
}ST;

//初始化
void STInit(ST* ps);//传的参数是结构体指针,指向栈
//销毁
void STDestroy(ST* ps);
//入栈
void STPush(ST* ps, STDataType x);//传的参数是结构体指针和数据
//出栈
void STPop(ST* ps);//传的参数是结构体指针和数据
//获取栈顶元素
STDataType STTop(ST* ps);//栈中元素的类型是STDataType,所以函数返回值的数据类型是STDataType
//获取栈中有效数据个数
int STSize(ST* ps);
//判空
bool STEmpty(ST* ps);

以上就是数据结构中栈的有关内容,谢谢观看!

相关推荐
菜鸟233号40 分钟前
力扣513 找树左下角的值 java实现
java·数据结构·算法·leetcode
FMRbpm1 小时前
队列练习--------最近的请求次数(LeetCode 933)
数据结构·c++·leetcode·新手入门
Neoest1 小时前
【EasyExcel 填坑日记】“Syntax error on token )“: 一次编译错误在逃 Runtime 的灵异事件
java·eclipse·编辑器
モンキー・D・小菜鸡儿1 小时前
Android Jetpack Compose 基础控件介绍
android·kotlin·android jetpack·compose
自在极意功。1 小时前
Web开发中的分层解耦
java·microsoft·web开发·解耦
是一个Bug2 小时前
ConcurrentHashMap的安全机制详解
java·jvm·安全
断剑zou天涯2 小时前
【算法笔记】bfprt算法
java·笔记·算法
番石榴AI2 小时前
java版的ocr推荐引擎——JiaJiaOCR 2.0重磅升级!纯Java CPU推理,新增手写OCR与表格识别
java·python·ocr
无风之翼2 小时前
android15 休眠唤醒过程中有时候屏幕显示时间一闪而过
android·锁屏
鸽鸽程序猿2 小时前
【项目】【抽奖系统】抽奖
java·spring