高效学习数据结构之栈和队列篇(五千字超详细教程)

这篇具有很好参考价值的文章主要介绍了高效学习数据结构之栈和队列篇(五千字超详细教程)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

大家好呀我是小生🙉🙊🙈今天我们来学习数据结构的栈和队列,小生为了方便大家理解特意附上了许多图片和源码一起加油吧🥳🥳🥳 高效学习数据结构之栈和队列篇(五千字超详细教程)

下面是我们今天要学习的内容🥳🥳🥳

 一.栈

         1.🏠栈的基本概念

​2.🏠栈的结构选择

🚀顺序表和链表的优缺点对比:

🚀用数组实现栈

🚀用单链表实现栈

🚀用带头双向循环链表实现栈

3.🏠栈的常见接口的实现

🚀栈的接口预览

​ 🚀栈的构成

 🚀栈的初始化

🚀栈的销毁

🚀压栈操作

🚀出栈操作

🚀取栈顶元素

🚀判断栈是否为空

🚀查找栈元素的个数

二.队列

1.🏠队列的基本概念

2.🏠队列的基本操作

🚀队列的基本接口

🚀队列的组成

​🚀队列的初始化

🚀队列的销毁

🚀入队

🚀出队

🚀寻找队头元素

🚀寻找队尾元素

🚀判断队列是否为空

🚀求队列容量

三.🏠小生想说的话


一.栈

1.🏠栈的基本概念

栈是一种线性表,只允许在固定的一端进行插入和删除操作进行数据插入删除的为栈顶,另一端为栈底。符合先进后出。既有数组栈和链式栈。

压栈:压栈就是栈的插入,也称之为入栈。

出栈:出栈就是栈的删除操作。

高效学习数据结构之栈和队列篇(五千字超详细教程)

2.🏠栈的结构选择

栈如何实现?是使用数组还是链表呢,在选择之前我们先了解一下顺序表与链表的优缺点:

🚀顺序表和链表的优缺点对比:

顺序表的优点: 

1.可以按下标进行随机访问

2.顺序表的CPU高速缓存命中率比较高。

顺序表的缺点:

1.空间不够需要扩容,会存在一定的空间浪费。

2.当头部或者中间插入删除数据,需要挪动数据,效率较低

链表的优点:

1.按需申请内存,不存在性能消耗,不存在空间浪费。

2.实现任意位置以O(1)的时间复杂度插入或者删除数据。

链表的缺点:

1.不支持下标的随机访问

2.顺序表的CPU高速缓存命中率比较高

🚀用数组实现栈

我们先来讨论一下数组,我们知道,我们永远是对栈顶进行操作,因此我们如果使用数组结构的话,应该将下标为0处设为栈底,将数组的末端设为栈顶因为如果我们将下标为0的地方设为栈顶的话每次进行入栈或者出栈操作,后面的元素必须向前挪动,从而导致复杂度过大。小生画个图大家看看,方便大家理解:

高效学习数据结构之栈和队列篇(五千字超详细教程)


🚀用单链表实现栈

既然我们可以用数组实现栈,那么小生想问一个问题🙊🙊🙊我们可以选择单链表吗?我们仔细想想,同样的道理,我们先来看看第一种方法:

高效学习数据结构之栈和队列篇(五千字超详细教程)

当我们用单链表将栈顶和栈底置为如上位置,我们发现入栈的时候,每次都需要用一个指针从头遍历整个链表找到尾结点,时间复杂度为O(n),因此这样会非常麻烦,为了优化我们的程序,可以使用一个pMove指针存放尾部结点的地址,但是这样真的能够从根本上解决问题吗?入栈的问题解决了,但是小生想说的是如果出栈怎么办?难道用两个指针一个存放尾结点的地址另一个指针存放倒数第二个结点的地址吗?如果我要多次出栈呢?哈哈想想看,是不是很难解决实际的问题,但是这种思考方式让我们联想到了带头的循环链表,我们后面再谈。那么单链表真的不能实现吗?我们来看看下面这种方式:

高效学习数据结构之栈和队列篇(五千字超详细教程)

或许你惊呆了,这两种猜想乍一看没什么区别,其实区别大了,猜想1在入栈和出栈的时候对链表进行的是尾插和尾删,我们可以知道,单链表每次尾插和尾删在很多时候都需要用pMove指针找尾结点,将该链表遍历一次,时间复杂度很大为O(n),但是第二种猜想我们用的是头插和头删,时间复杂度为O(1),因此第二种猜想明显符合我们栈的要求,非常便捷。 

🚀用带头双向循环链表实现栈

高效学习数据结构之栈和队列篇(五千字超详细教程)

通过以上的分析我们可以得出三种实现栈的方式,那么们如何选择,我们选择数组,因为它往CPU高速缓存命中率更加高。因此能用数组就不选择链表。那我们接下来便用数组实现栈

3.🏠栈的常见接口的实现

为了让大家看得更清楚,小生特意做成了图片和源码😎😎😎

🚀栈的接口预览

高效学习数据结构之栈和队列篇(五千字超详细教程) 🚀栈的构成

我们知道,数组栈首先需要的就是一个记录栈顶元素的下标还需要一个容量以便顺序表已满后扩容。🥳🥳🥳

高效学习数据结构之栈和队列篇(五千字超详细教程)

 🚀栈的初始化

这里小生提供两种初始化方式,可以直接初始化时不给数组空间,也可以初始化是该数组一定的空间,为什么要有第二种初始化方式呢?通过第二种初始化方法我们就可以让realloc直接实现二倍扩容,如果按照第一种初始化方式capacity扩大为原来的两倍后依然为0😭😭😭废话不多说,我们先来看看不给空间的初始化🙉🙉🙉

高效学习数据结构之栈和队列篇(五千字超详细教程)

void StackInit(Stack* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->capacity = 0;
	pst->top = 0;
}

看完了第一种,那让我们再来看看在初始化栈的时候给数组空间的情况:🙉🙉🙉
高效学习数据结构之栈和队列篇(五千字超详细教程)

void StackInit(Stack* pst)
{
	pst->a = (STDataType)malloc(sizeof(STDataType) * 4);
	pst->capacity = 4;
	pst->top = 0;
}

🚀栈的销毁

高效学习数据结构之栈和队列篇(五千字超详细教程)

void StackDestory(Stack* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->capacity = 0;
	pst->top = 0;
}

🚀压栈操作

高效学习数据结构之栈和队列篇(五千字超详细教程)

void Stackpush(Stack* pst, STDataType val)
{
	assert(pst);
	if (pst->top == pst->capacity)
	{
		STDataType* tmp = (STDataType)realloc(pst->a,sizeof(STDataType) * pst->capacity * 2);
		if (tmp == NULL)
		{
			printf("扩容失败!\n");
			exit(-1);
		}
		pst->a = tmp;
		pst->capacity *= 2;
	}
	pst->a[pst->top++] = val;
}

🚀出栈操作

高效学习数据结构之栈和队列篇(五千字超详细教程)

void StackPop(Stack* pst)
{
	assert(pst);
	assert(!StackEmpty(pst));
	pst->top--;
}

🚀取栈顶元素

高效学习数据结构之栈和队列篇(五千字超详细教程)

STDataType StackTop(Stack* pst)
{
	assert(pst);
	assert(!StackEmpty(pst));
	return pst->a[pst->top - 1];
}

🚀判断栈是否为空

高效学习数据结构之栈和队列篇(五千字超详细教程)

int StackEmpty(Stack* pst)
{
	return pst->top == 0;
}

🚀查找栈元素的个数

高效学习数据结构之栈和队列篇(五千字超详细教程)

int StackSize(Stack* pst)
{
	assert(pst);
	return pst->top;
}

栈到这里它的基本操作就已经完结啦,小生觉得在图片上注释比文字的方式应该更加通俗易懂大神们,接下来我们就要进入队列的学习啦,加油技术人!!!🥳🥳🥳

二.队列

1.🏠队列的基本概念

队列只允许在一端进行插入数据操作,在另一端进行删除操作。符合先进先出的原则。

队尾:进行插入操作的地方。

队头:进行删除操作的地方。

我们先通过一个图来认识一下队列的入队和出队操作🥳🥳🥳

高效学习数据结构之栈和队列篇(五千字超详细教程)

2.🏠队列的基本操作

🚀队列的基本接口

高效学习数据结构之栈和队列篇(五千字超详细教程)

🚀队列的组成

高效学习数据结构之栈和队列篇(五千字超详细教程)🚀队列的初始化

高效学习数据结构之栈和队列篇(五千字超详细教程)

void QueueInit(Queue* pQ)
{
	assert(pQ);
	pQ->pHead = pQ->pTail = NULL;
}

🚀队列的销毁

高效学习数据结构之栈和队列篇(五千字超详细教程)

void QueueDestory(Queue* pQ)
{
	assert(pQ);
	QueueNode * pMove = pQ->pHead;
	while (pMove)
	{
		QueueNode* pNext = pMove->pNext;
		free(pMove);
		pMove = pNext;
	}
	pQ->pHead = pQ->pTail = NULL;
}

🚀入队

高效学习数据结构之栈和队列篇(五千字超详细教程)

void QueuePush(Queue* pQ, QueueDataType val)
{
	assert(pQ);
	QueueNode* pNew = (QueueNode*)malloc(sizeof(QueueNode));
	assert(pNew);
	pNew->data = val;
	pNew->pNext = NULL;
	if (pQ->pTail == NULL)
	{
			
		pQ->pHead = pQ->pTail = pNew;
	}
	else
	{
		pQ->pTail->pNext = pNew;
		pQ->pTail = pNew;
	}
}

🚀出队

高效学习数据结构之栈和队列篇(五千字超详细教程)

void QueuePop(Queue* pQ)
{
	assert(pQ);
	assert(!QueueEmpty(pQ));
	if (pQ->pHead->pNext == NULL)
	{
		free(pQ->pHead);
		pQ->pHead = pQ->pTail = NULL;
	}
	else
	{
		QueueNode* pTmp = pQ->pHead->pNext;
		free(pQ->pHead);
		pQ->pHead = pTmp;
	}
}

🚀寻找队头元素

找队头元素和找队尾元素是最简单了啦,小生就不罗嗦了,直接上代码🥳🥳🥳

QueueDataType QueueFront(Queue* pQ)
{
	assert(pQ);
	assert(!QueueEmpty(pQ));
	return pQ->pHead->data;
}

🚀寻找队尾元素

QueueDataType QueueBack(Queue* pQ)
{
	assert(pQ);
	assert(!QueueEmpty(pQ));
	return pQ->pTail->data;
}

🚀判断队列是否为空

bool QueueEmpty(Queue* pQ)
{
	assert(pQ);
	return pQ->pHead == NULL;
}

🚀求队列容量

高效学习数据结构之栈和队列篇(五千字超详细教程)

int QueueSize(Queue* pQ)
{
	int size = 0;
	QueueNode* pMove = pQ->pHead;
	while (pMove)
	{
		size++;
		pMove = pMove->pNext;
	}
	return size;
}

三.🏠小生想说的话

当你看到这里的时候,咱们数据结构的栈和队列的基本操作你已经学完啦😎😎😎但是这其实只是数据结构的冰山一角罢了,小生后续会不断更新数据结构的基础与拓展。如果大神们觉得有帮助的话别忘了三连哦,加油,技术人!!!🥳🥳🥳 

高效学习数据结构之栈和队列篇(五千字超详细教程)文章来源地址https://www.toymoban.com/news/detail-404197.html

到了这里,关于高效学习数据结构之栈和队列篇(五千字超详细教程)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言数据结构——线性表之栈和队列

    为什么会定义栈和队列这两种数据结构呢? 原因在于: 之所以会定义栈和队列这样的数据结构 是因为他们有两大特性 : 第一: 他们可以保存程序运行路径中各个点的信息,以便用于回溯操作或其他需要访问已经访问过的节点信息的操作。 比如: 栈用于解决迷宫问题,就

    2023年04月11日
    浏览(113)
  • 数据结构之栈和队列 - 超详细的教程,手把手教你认识并运用栈和队列

    栈:后进先出 队列:先进先出 栈:是一种特殊的 线性表 , 只允许在固定的一端插入或者删除元素 ,一个栈包含了栈顶和栈底。只能在栈顶插入或者删除元素。 栈的底层 是由 数组 实现的。 栈遵循先入后出原则,也就是先插入的元素得到后面才能删除,后面插入的元素比

    2024年02月07日
    浏览(83)
  • 数据结构--》深入了解栈和队列,让算法更加高效

            本文将带你深入了解数据结构栈和队列,这两种基础的线性数据结构在算法中的重要性不言而喻。我们将会详细介绍栈和队列的概念、分类、实现以及应用场景,在理解栈和队列的基础上,还将探讨如何通过栈和队列来高效地解决算法问题。         无论你是

    2024年02月10日
    浏览(40)
  • 《数据结构》之栈和堆结构及JVM简析

    在数据结构中,我们第一了解到了栈或堆栈,它的结构特点是什么呢?先进后出,它的特点有什么用呢?我们在哪里可以使用到栈结构,栈结构那么简单,使用这么久了为什么不用其它结构替代? 作为一个程序猿,我们应该会常常跟代码打交道,那么我们所编写的程序或代码

    2024年02月07日
    浏览(51)
  • 【数据结构】线性表之栈、队列

    前面两篇文章讲述了关于线性表中的顺序表与链表,这篇文章继续讲述线性表中的 栈和队列。 这里讲述的两种线性表与前面的线性表不同,只允许在一端入数据,一段出数据,详细内容请看下面的文章。 顺序表与链表两篇文章的链接: 线性表之顺序表 线性表之链表 注意:

    2024年02月06日
    浏览(62)
  • 数据结构之栈、队列——算法与数据结构入门笔记(四)

    本文是算法与数据结构的学习笔记第四篇,将持续更新,欢迎小伙伴们阅读学习 。有不懂的或错误的地方,欢迎交流 栈是一种线性数据结构,其 只允许在固定的一端进行插入和删除 元素操作。进行数据插入和删除操作的一端称为栈顶 (Top), 另一端称为栈底 (Bottom)。栈中的

    2024年02月08日
    浏览(39)
  • 数据结构之栈与队列详解

    栈和队列是一种特殊的线性结构,他与之前学的线性结构不同,栈和队列是拥有一种特殊规则的线性结构,虽然它是用数组或者链表实现,但是只有符合这种规则才能被称作栈或者队列 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和

    2024年01月16日
    浏览(53)
  • Java------数据结构之栈与队列(简单讲解)

    本篇碎碎念 :时隔n个月,继续写博客,假期落下的进度,在开学后努力追赶, 假期不努力,开学徒伤悲啊,此时此刻真想对自己说一句,活该啊~~~~ 欠下的链表练习题讲解会在下次更新~~~~ 今日份励志文案:  万物皆有裂痕,那是光照进来的地方 栈:一种特殊的线性表,其只允

    2024年04月14日
    浏览(58)
  • 数据结构之栈与队列的实现与详细解析

    个人主页:点我进入主页 专栏分类:C语言初阶      C语言程序设计————KTV       C语言小游戏     C语言进阶 C语言刷题       数据结构初阶 欢迎大家点赞,评论,收藏。 一起努力,一起奔赴大厂。 目录 1.前言 2.栈 2.1栈的概念与性质 2.2栈的实现 3.队列 3.1队列的概

    2024年02月05日
    浏览(45)
  • Java 数据结构之栈、队列(头歌平台,详细注释)

    目录 第1关:实现基于数组的 任务描述 相关知识 栈 栈的数组表示 Java 泛型简介 泛型方法 泛型类应用场景示例 代码:  第2关:实现基于链表的栈 任务描述 相关知识 栈的链式存储 入栈 出栈 代码:  第3关:基于数组的队列 任务描述 相关知识 队列 队列的数组实现 循环队列

    2024年04月25日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包