数据结构------栈(Stack)和队列(Queue)

也是好久没写博客了,那今天就回归一下,写一篇数据结构的博客吧。今天要写的是栈和队列,也是数据结构中比较基础的知识。那么下面开始今天要写的博客了。

目录

栈(Stack)

队列(Queue)

喜欢就点个赞吧。


栈(Stack)

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

 

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

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

简单描述栈的特点:栈数据的增删都是在一头进行,即在栈顶


那栈又该如何创建与使用呢?他的原理又是怎样的,这里我们就用C语言实现一下。

我们这里就要想这个栈是要用数组来实现还是用链表来实现呢?其实我们可以从其功能开始思考,这两者哪个更好去实现栈的功能,而且效率较高,其实说到这里,很多人可能已经有了结果,其实要说简洁与效率数组更适合来做栈。那么我们下面就来完成一下这个代码完成一个栈。

这里先给头文件因为其中有typedef来命名的类型,以免各位佬看得迷惑。

头文件

这里解释一下DataType是各位做栈时储存数据的类型,需要改变时只需要在头文件里改动一下即可,例如你想变成char类型的数据,即可将typedef int DataType; 改为 typedef char DataType;
然后栈的结构体我们就用ST来简化方便写代码。

然后top为栈的数据个数,capacity就表示栈的容量
 

#pragma once
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#include <stdlib.h>
typedef int DataType;

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


void StackInit(ST* ps);
void StackDestory(ST* ps);
// 入栈
void StackPush(ST* ps, DataType x);
// 出栈
void StackPop(ST* ps);
DataType StackTop(ST* ps);

int StackSize(ST* ps);
bool StackEmpty(ST* ps);

 

栈的格式化

void StackInit(ST* ps)
{
	assret(ps);
	ps->a = (DataType)mallco(4 * (sizeof(DataType)));
	if (ps->a == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	ps->capacity = 4;
	ps->top = 0;

}

先将数组a  mallco出四个数据的大小,然后将容量capacity改为4.


栈的销毁

void StackDestory(ST* ps)

{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->top = ps->capacity = 0;

}

使用完栈后进行销毁得函数,防止内存泄露。 及时free掉,然后将a指向NULL。


入栈 

void StackPush(ST* ps, DataType x)
{
	assert(ps);
	if (ps->top == ps->capacity)
	{
		DataType* tem = (DataType*)recalloc(ps->a, 2*ps->capacity*sizeof(DataType));
		if (tem == NULL)
		{
			printf("racallco fail\n");
		}
		else
		{
			ps->a = tem;
			ps->capacity = 2 * ps->capacity;
		}

	}

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

第一个if,先判断数组a是否还有空间入栈,如果满了就进行recallco增容即可增容我们现在时增容两倍较为合适,recallco的用法在前面动态内存创建的文章已经讲过了。所以现在就不多解释了。入栈后记得将top++一下 。


出栈

void StackPop(ST* ps)
{
	assert(ps);
	assert(ps->top > 0);

	
	ps->top--;
}

这里就比较简单粗暴将top--,即可将原本栈顶得书局给屏蔽即可。


求栈的长度和判断栈是否为空 

int StackSize(ST* ps)
{
	assert(ps);
	return ps->top;
}


bool StackEmpty(ST* ps)
{
	assert(ps);

	return ps->top == 0;
}

 

接下来我们就来看看队列


队列(Queue)

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先 进先出FIFO(First In First Out)

 

队列的特点:队列与栈的不同是他是在一头进行增数据,一头删数据,而栈数据的增删都是在一头。

 然后我们思考一下队列的功能实现是要数组好还是链表好呢,这么一想是不是马上就发现了,如果们还是用数组来实现的话,那么其出队列的时间复杂度为O(N),那么效率太低了,而链表实现的话则是O(1),显而易队列还是用链表实现较好。


下面就是队列函数的实现了。

还是先给大家看看头文件

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>
#include <stdlib.h>

typedef int Type;

typedef struct Queuenode 
{
	Type* date;
	struct Queue* next;

}Node;


typedef struct Queue
{
	Node* head;
	Node* tail;
}Queue;


void QueueInit(Queue* pq);
void QueueDestory(Queue* pq);

// 队尾入
void QueuePush(Queue* pq, Type x);
// 队头出
void QueuePop(Queue* pq);

这里解释一下为什么创建了两个结构体 ,因为其中一个作为链表的节点而另一个队列结构体。队列的结构体我们只需要要一个队头和队尾。


 队列的格式化

 

void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = NULL;
	pq->tail = NULL;



}

很简单将队头和队尾指向空NULL即可。


队列的销毁

void QueueDestory(Queue* pq)
{
	assert(pq);

	Node* cur = pq->head;
	while (cur)
	{
		Node* next = cur->next;
		free(cur);
		cur = next;

	}

	pq->head = pq->tail = NULL;


}

 这里我们运用一个while循环,创建一个辅助指针来保存节点的下一个。不断free 掉即可。

注意要将队头和队尾指空NULL。


进队

 

void QueuePush(Queue* pq, Type x)
{
	assert(pq);
	Node* new = (Node*)mallco(sizeof(Node));
	if (new == NULL)
	{
		printf("mallco fail\n");
	}
	new->date = x;
	new->next = NULL;
	if (pq->tail = NULL)
	{
		pq->tail = new;
        pq->head = new;
	}


	else
	{
		pq->tail->next = new;
		pq->tail = new;

	}

}

 我们mallco一个空间,作为进队的一个节点,然后对节点进行赋值,然后对链表进行尾插就完成了一半了。

需要注意的是记得把原来的tail的next 指向新节点,也要把tail改为 新节点,因为尾插后new就为最后的节点也就是尾了。注意当前有没有节点那将head和tail至为new即可。


出队

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->head);
	
	if (pq->head->next == NULL)
	{
		free(pq->head);
		pq->head = NULL;
		pq->tail = NULL;
	}


	Node* next = pq->head->next;
	free(pq->head);
	pq->head = next;



}

 这里也是根据队列的删数据特点,这里的出队就是头删了,我们先把head的next保存住,然后free掉head,再然后让next作为新的头。

 


 今天就结束了,希望您能喜欢这篇文章。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/417411.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从C到C++

二、从C到C 本章介绍一些C拓展的非面向对象功能。 引用&#xff08;掌握&#xff09; 1.1 概念 引用从一定程度上讲是一个指针的平替&#xff0c;几乎被所有面向对象编程语言所使用。引用相当于对某一个目标变量起”别名“。 操作引用与操作原变量完全一样。 #include <iost…

工厂模式 详解 设计模式

工厂模式 其主要目的是封装对象的创建过程&#xff0c;使客户端代码和具体的对象实现解耦。这样子就不用每次都new对象&#xff0c;更换对象的话&#xff0c;所有new对象的地方也要修改&#xff0c;违背了开闭原则&#xff08;对扩展开放&#xff0c;对修改关闭&#xff09;。…

Unity UI适配规则和对热门游戏适配策略的拆解

前言 本文会介绍一些关于UI适配的基础概念&#xff0c;并且统计了市面上常见的设备的分辨率的情况。同时通过拆解目前市面上较为成功的两款休闲游戏Royal Match和Monopoly GO(两款均为近期游戏付费榜前几的游戏)&#xff0c;大致推断出他们的适配策略&#xff0c;以供学习和参…

go并发模式之----阻塞/屏障模式

常见模式之一&#xff1a;阻塞/屏障模式 定义 顾名思义&#xff0c;就是阻塞等待所有goroutine&#xff0c;直到所有goroutine完成&#xff0c;聚合所有结果 使用场景 多个网络请求&#xff0c;聚合结果 大任务拆分成多个子任务&#xff0c;聚合结果 示例 package main ​…

Delegate动画案例(P30 5.6delegate动画)

一、ListElement&#xff0c;ListModel&#xff0c;ListView 1. ListElement ListElement 是 QML 中用于定义列表项的元素。它可以包含多个属性&#xff0c;每个属性对应列表项中的一个数据字段。通过在 ListModel 中使用 ListElement&#xff0c;可以定义一个列表的数据模型…

USB-C接口:办公新宠,一线连接笔记本与显示器

USB-C接口如今已成为笔记本与显示器连接的优选方案。无需担心正反插错&#xff0c;支持雷电4和DP视频信号输出&#xff0c;高速数据传输&#xff0c;还有最高100W的快充功能&#xff0c;真是方便又实用&#xff01; 一线连接&#xff0c;多功能融合 通过这个接口&#xff0c;你…

面试笔记系列三之spring基础知识点整理及常见面试题

目录 如何实现一个IOC容器? 说说你对Spring 的理解&#xff1f; 你觉得Spring的核心是什么&#xff1f; 说一下使用spring的优势&#xff1f; Spring是如何简化开发的&#xff1f; IOC 运行时序 prepareRefresh() 初始化上下文环境 obtainFreshBeanFactory() 创建并…

瑞_23种设计模式_外观模式

文章目录 1 外观模式&#xff08;Facade Pattern&#xff09;1.1 介绍1.2 概述1.3 外观模式的结构 2 案例一2.1 需求2.2 代码实现 3 案例二3.1 需求3.2 代码实现 4 jdk源码解析 &#x1f64a; 前言&#xff1a;本文章为瑞_系列专栏之《23种设计模式》的外观模式篇。本文中的部分…

如何在Windows部署TortoiseSVN客户端并实现公网连接内网VisualSVN服务端

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统&#xff0c;它与Apache Subversion&#xff08;SVN&#xff09;集成在一起&#xff0c;提供了一个用户友好的界面&#xff0c;方便用…

Flutter开发之Slider

Flutter开发之Slider 本文是关于介绍Slider相关属性的含义。 class SliderThemeData {/// slider轨道的高度 final double? trackHeight; /// 滑块滑过的轨道颜色 final Color? activeTrackColor; /// 滑块未滑过的轨道颜色 final Color? inactiveTrackColor; /// 滑块滑过…

JavaEE——简单认识JavaScript

文章目录 一、简单认识 JavaScript 的组成二、基本的输入输出和简单语法三、变量的使用四、JS 中的动态类型图示解释常见语言的类型形式 五、JS中的数组六、JS 中的函数七、JS 中的对象 一、简单认识 JavaScript 的组成 对于 JavaScript &#xff0c;其中的组成大致分为下面的…

多线程如何设计?一对多/多对一/多对多

二、14个多线程设计模式 参考原文&#xff1a;https://www.cnblogs.com/rainbowbridge/p/17443503.html single Thread 模式 一座桥只能通过一个人 Single Thread模式是一种单线程设计模式&#xff0c;即在一个应用程序中只有一个主线程、一个事件循环&#xff0c;对外只提…

【C语言基础】:深入理解指针(一)

文章目录 一、内存和地址1. 内存2. 如何理解编址 二、指针变量和地址2.1 取地址操作符(&)2.2 指针变量和解引用操作符(*)2.2.1 指针变量2.2.2 如何拆解指针变量2.2.3 解引用操作符 2.3 指针变量的大小 三、指针变量类型的意义3.1 指针的解引用3.2 指针 - 整数3.3 void*指针…

什么是物联网?

今天这篇文章写的相关内容就是带领大家了解什么是物联网&#xff0c;之前写的文章大多都是一些物联网的未来&#xff0c;行业的解决方案等&#xff1b;话不多说开始进入正题吧! 物联网(IoT)是一个包罗万象的术语&#xff0c;指的是越来越多的电子产品&#xff0c;它们不是传统的…

vue2+elementui上传照片(el-upload 超简单)

文章目录 element上传附件&#xff08;el-upload 超详细&#xff09;代码展示html代码data中methods中接口写法 总结 element上传附件&#xff08;el-upload 超详细&#xff09; 这个功能其实比较常见的功能&#xff0c;后台管理系统基本上都有&#xff0c;这就离不开element的…

计算机组成原理4-存储器的层次结构与程序访问的局部性原理

1. 磁盘 1.磁盘的结构 磁盘由盘片构成&#xff0c;每个盘片包含两面 每面由一组称为磁道的同心圆组成 每个磁道划分为一组扇区&#xff0c;扇区之间由间隙隔开 同一半径上的所有磁道组成一个柱面2.磁盘的容量 容量&#xff1a;磁盘上可以存储的最大位数。 决定因素&#xff1a…

【玩转408数据结构】线性表——双链表、循环链表和静态链表(线性表的链式表示 下)

知识回顾 在前面的学习中&#xff0c;我们已经了解到了链表&#xff08;线性表的链式存储&#xff09;的一些基本特点&#xff0c;并且深入的研究探讨了单链表的一些特性&#xff0c;我们知道&#xff0c;单链表在实现插入删除上&#xff0c;是要比顺序表方便的&#xff0c;但是…

IDEA利用鼠标调整字体大小

就可以按住ctrl和鼠标调节代码字体的大小啦&#xff01; 如果有用&#xff0c;记得给我来个赞~ 谢啦&#xff01;

【python基础学习07课_函数基础课】

一、函数的基础知识 一、函数的作用是用来干什么的&#xff1f; 函数在编程中是一个组织好的、可重复使用的代码块&#xff0c;用于执行一个特定的任务。具体来说&#xff0c;函数的常见作用包括&#xff1a;1、执行计算或数据处理。 2、控制程序的流程&#xff0c;如条件判断…

Java+SpringBoot+Vue+MySQL:员工健康管理技术新组合

✍✍计算机毕业编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java、…