
姚哥数据结构与算法
文章平均质量分 80
姚哥对数据结构与算法的介绍总是充满了趣味和智慧,让人捧腹却又不失深度。
以幽默和生动的比喻,姚哥让每个人在学习数据结构与算法时都能感受到乐趣,轻松掌握这些重要的编程基础。通过这样的介绍,大家不仅学会了知识,更明白了它们在实际应用中的重要性。
国中之林
难的学不会是因为简单的没学好!学习交流加wx:1032090014
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
【数据结构与算法】顺序表
总的来说,顺序表的应用十分广泛,它在许多领域中都发挥着重要的作用,特别是当需要快速随机访问数据时。相当于是数组的升级版可以进行插入和删除数据,使其更加的灵活.原创 2024-07-27 11:42:35 · 562 阅读 · 0 评论 -
【数据结构与算法】链表
链表的优势一看便知,就是插入删除数据不需要移动大量的数据,可以直接进行.其缺点也是显而易见,不方便访问,每次都需要从头遍历.任意位置插入和删除都需要找到前一个节点位置,需要从头节点开始,区别是循环条件插入是p删除是p->next获取和查找因为头节点没有数据,都是从头节点的下一个节点开始.我们需要的是最后一个节点,还是遍历完,最后一个节点的循环条件是p->next,遍历完是p获取前一个节点循环条件是index原创 2024-07-28 16:53:34 · 718 阅读 · 0 评论 -
【数据结构与算法】循环链表
循环链表与单链表的不同点就在尾巴上.原创 2024-07-29 11:17:15 · 964 阅读 · 2 评论 -
【数据结构与算法】双向链表
双向链表比单链表多了一个指向前一个位置的指针,方便了我们进行查找,对插入和删除的时候,我们可以将目标放在我们想要的上面.需要注意插入和删除的操作,多了一个前面指针的赋值.原创 2024-07-29 14:50:15 · 1180 阅读 · 0 评论 -
【数据结构与算法】共享双向链表
共享链表,可以这样想象,首先,数据域与指针域是分开的.链表只关心指针域.然后通过结构体来关联数据和链表.相当于一个个结构体通过其数据成员设置为链表进行关联.又通过链表的地址与结构体的偏移量来获取结构体的地址.从而可以对数据进行访问看似是松散的,其实是紧密连接的,数据可以是任意的,链表的接口是不变的,从而达到了共享的目标.任何数据类型都可以用这只有指针域的链表.原创 2024-07-29 19:57:19 · 655 阅读 · 0 评论 -
【数据结构与算法】队列(顺序存储)
其实当你熟悉了顺序表,那么顺序存储的队列很简单,就是数组,只不过我们特殊在头和尾部的操作.队列是一种先进先出(FIFO)的数据结构。队列通常具有两个基本操作:入队和出队。入队操作将元素添加到队列的末尾。出队操作将队列的第一个元素删除并返回。队列的底层实现可以使用数组或链表。原创 2024-07-30 14:09:56 · 1038 阅读 · 0 评论 -
【数据结构与算法】链队列
链队列是使用链表实现的队列,与顺序队列相比,链队列的插入和删除操作更高效,不需要移动元素。链队列的重要特点是使用头指针和尾指针分别指向链表的头部和尾部,可以快速执行入队和出队操作。原创 2024-07-30 19:40:58 · 361 阅读 · 0 评论 -
【数据结构与算法】循环队列
循环队列是一种基于数组实现的队列数据结构,它的特点是可以通过循环利用数组的空间来实现高效的出队和入队操作。循环队列中通常会用到两个指针,分别指向队首和队尾。当队满时,队尾指针会绕回到数组的开头;当队空时,队首和队尾指针相等。循环队列在实际应用中常用于实现缓冲区等场景,可以提高空间利用率和操作效率。原创 2024-07-31 19:55:50 · 336 阅读 · 0 评论 -
【数据结构与算法】优先级队列
可以联想我们现实中排队时,有个军人优先服务.那么这个就是一个优先级队列.后面入队的,但是根据优先级,我可以先出.使用二级指针是为了能够修改一级指针指向的内存地址,从而改变链表节点的指向关系。在这段代码中,通过使用二级指针prev来记录最高优先级节点的上一个节点的next指针地址,可以在删除节点时直接修改链表的指向关系,而不需要再通过一个中间变量来保存上一个节点的地址。同时,二级指针也能够处理特殊情况,例如删除最后一个节点或者删除头节点时需要修改队列的rear指针。原创 2024-08-01 12:00:27 · 294 阅读 · 0 评论 -
【数据结构与算法】堆
在现实生活中,我们经常会有比赛,比赛呢,往往会有冠军,亚军等等我们几乎所有人都只会记住冠军,但是很少有人会记住亚军,就像劳大说过的一句话:"第二是最大的失败者!"但是有的情况,第二还真的就不一定是第二,当裁判们发现了第一名作弊,那么我们就会将亚军升成冠军.那么这样就需要我们对排序进行保存,这样才能很好的,供我们操作,所以我们就选用了**堆**来做为排序的存取.我们要知道堆的特性,这样我们才能用数组来创建堆.其次就是公式,父节点找子节点,子节点找父节点.还有如何比较来创建堆.原创 2024-08-02 09:54:02 · 798 阅读 · 0 评论 -
【数据结构与算法】堆的插入
上一节我们已经能够创建最大堆了,但是是一个静态的,如果我们插入数据,会产生什么样新的火花呢?插入一个元素,我们一般插入在末尾来维持前面堆的特点.很明显,现在的图不是一个最大堆.开始向上调整:传入的是新插入元素的下标,不是元素个数.先保存子节点的值,然后找到父节点进行对比,然后再把父节点当成子节点,继续向上比较,如果还有父节点的话.插入都是从尾部插入,那么我们建堆又有了一种方法:原创 2024-08-02 11:37:53 · 359 阅读 · 0 评论 -
【数据结构与算法】堆顶删除
删除堆的操作可以分为两个步骤:删除根节点和调整堆。将根节点与最后一个节点进行交换;删除最后一个节点;更新堆的大小。从根节点开始,与其子节点比较,找到较大(小)的子节点;如果根节点小于(大于)子节点,则交换两者的值;重复上述步骤,直到节点没有子节点或满足堆的性质。删除堆的操作时间复杂度为O(log n),其中n是堆的大小。原创 2024-08-03 11:30:50 · 491 阅读 · 0 评论 -
【数据结构与算法】堆实现优先级队列
用堆来实现优先级队列真是一种不错的选择!原创 2024-08-03 19:18:18 · 281 阅读 · 0 评论 -
【数据结构与算法】堆排序
堆的排序,我们都要想办法将堆顶进行操作!原创 2024-08-05 09:24:19 · 355 阅读 · 0 评论 -
【数据结构与算法】栈
栈是一种后进先出(LIFO)的数据结构。它有两个主要操作:入栈(push)将元素放入栈的顶部,出栈(pop)将栈顶部的元素移除。栈还有一个常用的操作是查看栈顶元素(peek),即获取栈顶元素的值而不进行移除。原创 2024-08-05 14:11:00 · 833 阅读 · 0 评论 -
【数据结构与算法】链栈(恋战)
我们上节课用的数组来实现,现在我们用链式存储来实现,其实跟链队列基本一样,只不过是出栈的位置不一样而已.不同点来了,从栈顶进行出栈.注意出到最后一个元素的情况.与链队列完全一样,注意当插入第一个节点时的情况.用一个头来当栈,每个节点作为链子.原创 2024-08-06 11:38:35 · 390 阅读 · 0 评论 -
【数据结构与算法】迷宫求解------回溯法
当我们想要找到迷宫的出口,那我们在计算机中,然后操作,可以将每个位置都人栈,然后进行上下左右的路的判断,能否通过,若是死路,就将这个点出栈,回退到刚刚的栈,再判断其他的道路.在同行同列且相邻且在二维数组范围内,值为1就是通道就可以下一步.就当前入口点入栈,然后做标记改为2,就是我们走过的地方.就出栈,进行判断上一个路口,是否可以其他的下一步.地图的结构就是一个二维数组,初始化就是进行赋值.只有我们的栈不为空或者找不到出口,那么就一直找.初始化栈就可以进入到我们的迷宫判断了.能下一步就做标记,入栈.原创 2024-08-06 12:06:34 · 912 阅读 · 0 评论 -
【数据结构与算法】栈的应用——表达式求值
我想了一下,我主要写博客的目标还是说为了自己,自己容易忘记,相当于自己来过一遍,所以这是写给我自己的,当然如果你也遇到了相同的问题,那么不防我们可以一起探讨一下.原创 2024-08-10 16:43:58 · 5074 阅读 · 1 评论 -
【数据结构与算法】二叉树
当找到要删除的节点后,如果要删除节点的左边为空,就将姚删除节点的右边节点连接到要删除节点的位置,同理姚删除节点的右边为空的时候,就将要删除节点的左边连接到要删除的节点.我们这里选择找右子树的最小值,先将要删除节点的右孩子找到,然后根据二叉搜索树的性质,我们需要一直找其左子节点,能够找到最小的值.如果要插入的数据小于根节点的数据,就往左边遍历,否则右边遍历,直到tmp为空,那么parent就是要删除节点的父节点.如果当前节点不为空,同时当前节点的数据不是我们要删除的数据,那么我们一直遍历.原创 2024-08-10 20:39:42 · 1069 阅读 · 0 评论 -
【数据结构与算法】树的搜索和遍历
递归实现虽然简单,但是栈空间是有限的,递归多了,就容易溢出,所以数据多的话,我们可以使用栈。如果不相等就一直赋值其孩子来循环比较,直到孩子为空都没有找到的话,就说明没有.因为我们是栈顶元素先出,所以左孩子后入栈就先出站,直到栈为空为止.目的是要找到与我们给的值相等的节点,如果不相等就需要递归寻找.然后根节点出栈并打印,如果有右孩子先入栈,如果有左孩子后入栈.先将栈姚用到的接口定义好,这里栈中保存的数据类型为树的节点.目标值比要比的值小就向左递归,反之向右递归.先初始化栈并将我们的根节点入栈.原创 2024-08-11 11:42:09 · 529 阅读 · 0 评论 -
【数据结构与算法】二叉树——哈夫曼编码
那么刚好就像我们树的叶子,我们只需要将这些字符放在树的叶上,就能保证每一个字符的编码都不一样,从根节点向左我们记作0,向右我们记作1.因为是优先级队列,不用在乎插入在什么位置,这里是用的前插法,是为了新结合的节点与频率相同节点先进行结合.如果我们对出现的频率进行计算:空格出现5,w出现4,l出现4,e出现2,i出现2,r出现1,u出现1.队列里面装的是树.树包含值就是字符,还有权重就是出现次数,还有父节点,左孩子,右孩子节点。我们可以看成,树的层次越多,那么编码的位数就越大,那么出现的频率就越低.原创 2024-08-11 20:18:31 · 1248 阅读 · 0 评论 -
【数据结构与算法】哈希表
我们来看哈希表的几个重要的组成成分,编号我们称之为关键码(key),对关键码取模这是一种散列函数,当然不止取模.取模是最常见的.有动态分配内存的地方,我们就要释放,我们要对节点释放,对头结点释放,对头结点数组释放,对哈希表释放.ListNode是节点,其中包含关键码,数据,和指向下一个节点的指针.如果不存在,我们就动态分配一个节点,对其赋值,然后插入其中.因为我们查找是得到的节点,所以我们用这个来获取节点的数据.首先我们需要先进行查找,因为我们的编号是具有唯一性的.原创 2024-08-12 15:57:24 · 937 阅读 · 0 评论 -
【数据结构与算法】哈希表的顺序存储实现
当我们不需要大量的删除和插入数据时,那么这种哈希顺序表的优点就比哈希链表大.我们哈希表的插入和删除就是对顺序表的插入和删除,所以我们来设置顺序表接口.哈希函数找到目标顺序表,然后姚先判断关键值存不存在,不存在才可以插入.还记得乾坤大罗伊吧,哈哈,删除就是往前移动,删除边界值,直接减减.上一章是哈希链表,这一次我们结合顺序表,来一个哈希顺序表.哈希表数组里面直接是顺序表,顺序表中是数据.先找到在那个数组中,然后遍历顺序表对比.先找到目标顺序表,然后依次遍历对比删除.然后,动态分配数组.原创 2024-08-13 16:10:21 · 776 阅读 · 0 评论 -
【数据结构与算法】哈希表——字符串匹配
跟原来一样,只不过关键码的类型不在是整型了,c++中的字符串是const char*,所以这里用的const void*.原来我们讲的都是以整数作为关键码,那么我们可不可以用字符串来作为关键码呢?可以将不同的字符串转换成为不同的数字,就方便我们进行取余分组了.这是关键码的类型改变了一下,其他都一样,就不讲了.答案是基本思想还是不变,哈希函数求余来进行分组.那么如果我们也想用哈希表存储,我们该怎么办呢?那么就需要我们进行转换了,就是大名鼎鼎的。有的时候我们希望能够很快的查找字符串.但是字符串怎么可能求取呢?原创 2024-08-13 19:12:02 · 510 阅读 · 0 评论 -
【数据结构与算法】图
但是有一个缺点就是我们要找到目标路径需要遍历节点,因为每个节点相关联边的节点有很多,需要逐一比对,才能知道有没有目标路径.所以大多数的情况下,我们都是用的邻接列表,而不是矩阵,除非每个节点都与很多节点相关联.因为我们是输入的数据,我们要找到其在数组中的下标,然后再用前插法,插入到顶点之后.这就是与节点关联的边,将邻接的顶点记录下来,还有指向下一个与节点关联的边.先输入顶点数和边数,和顶点的数据,并将各个顶点相关联的边设置为空.需要有数据和与之相关联的第一条边.,其他的可以连接在边的后面.原创 2024-08-14 11:40:34 · 712 阅读 · 0 评论 -
【数据结构与算法】邻接列表的深度优先遍历
A->E->D,当我们到D的时候,我们无法再继续下去,那么我们就回退到E,E又回退到A,然后又可以访问到C,C的下一个我们已经访问过,就可以再回退到A,如果又遍历到B,B的下一个已经访问过,我们继续回退.这样所以的节点就访问到了,这就是深度优先遍历,当我们访问到一个节点后,那么继续访问该节点能访问的节点,直到走不通了再回退.因为我们是从某个点进行的遍历,如果这种情况,我们只对对A进行深度遍历的话,那么F是没有遍历到的.首先我们对该点的信息进行打印,并且将已经访问到的,该数组对于的下标设置为true.原创 2024-08-14 16:59:39 · 711 阅读 · 0 评论 -
【数据结构与算法】邻接列表的广度优先遍历
先对顶点入队,然后访问之后出队,再将顶点的邻接顶点入队,一直这样循环下去直到队列为空.访问过的记得要设置true.广度顾名思义就是广,哈哈,如果我们从A点开始的话.将一个顶点先入队,然后出队,再将其相邻的节点入队.对于这种按顺序的,先进先出的,我们可以采用队列.那么顺序就是A->E->C->B->D.这里我们用的c++标准库自带的队列.2024年8月14日20:13:14。原创 2024-08-14 20:14:26 · 424 阅读 · 0 评论 -
【数据结构与算法】最短路径算法
顾名思义根据需求,可以获取的最优的路径.比如说:我标的数值,就是时间,那么假如我们是A点到D点.那么我们可以看到有三条路径:A->E->D所花时间:36分钟A->C->D所花时间:25分钟A->B->D所花时间:26分钟那么如果我们根据时间来看待问题的话,那么A->C->D就是我们的最短路径.当然也可以其他的信息作为我们的判断,我们称之为权重.下面我们将用深度优先的方式来实现最短路径算法.原创 2024-08-15 11:28:31 · 467 阅读 · 0 评论 -
【数据结构与算法】A*算法——自动寻路
如果越界了不可以,因为是一个二维数组,如果是障碍物不可以,这里我们在二维数组中设置的值为1的是障碍物.,如果在closeList的也不可以,因为我们已经走过了.对于周围每个可以走通的格子我们进行判断是否在openList里面,如果没有就加入,有的话,就判断需不需要进行更新.判断的依据就是G是否更小,因为H都是一样的.很明显,我们要得到最短的,那么就需要比较,就需要我知道所有的路径,然后比较出最短的,那么我需要知道所有的路径这是非常庞杂的工作.G是起点格子到该格子的步数,H是该格子到终点格子的步数.原创 2024-08-16 17:31:45 · 2193 阅读 · 1 评论 -
【数据结构与算法】分治法
于是节目组从低到高的给我排了10个妹子,但是有一堵墙,我看不到她们,只能问他她们.就在这时,我突然想到,既然是按顺序排的,那我何不从中间问起,一下就可以排除一半.但是只给我4次的询问机会,如果4次内找到就领回家,否则就答应节目组与翠花交往.每次都是比较中间的,大就继续比较大的那部分中间,小就比较小的那部分中间.将一个大问题,拆解成为若干个小问题,而且大问题与小问题的解决方法一样.然后在剩下的一半中,我还是从中间问起,一下又可以排除一半.我想了一想,区区小事,何足挂齿,就答应了下来.分:递归解决较小的问题。原创 2024-08-16 20:52:39 · 477 阅读 · 2 评论 -
【数据结构与算法】动态规划
当我在递归f(5)的时候已经计算了f(4),f(3)这些,但是当我递归f(4)的时候又要计算f(4),f(3)就导致了大量的重复的计算,实在是不可取.因为f(2)和f(1)可以一眼看出,我们可以当成已知条件,f(2)为2种方式(两步都为1步或者一次两步),f(1)为1种方式.我们知道f(1)和f(2)的值,那么我们就可以算出f(3),如果将f(3)的值保存,我们就可以算出f(4)…简化就是:f(5)=f(4)+f(3),递推那么f(4)=f(3)+f(2),f(3)=f(2)+f(1)原创 2024-08-17 11:11:50 · 417 阅读 · 0 评论 -
【数据结构与算法】回溯法
假如就像这种情况,我们是先判断的左上右下,那么我们就会先走左边F,然后又匹配到C,C很明显就匹配不到E了,所以我们需要回退,回退的时候,我们要将比对的字符也回比上一个,同时将这些改成为为访问,有可能别的路径会访问到这里.因为字符串的结尾是’\0’,如果都匹配到这里了,那么说明,我们的字符串就找完了,有路径,返回true,也是递归的结束条件.上次我们用的是栈去实现求解的迷宫的问题,现在我们去使用递归的方式来达到回退的方式,来完成一个字符串路径的问题.2024年8月17日16:12:57。原创 2024-08-17 16:14:16 · 551 阅读 · 0 评论 -
【数据结构与算法】贪心算法
贪心顾名思义,比如说现在我贪玩,不卷,那么我以后可能会不爽,但是现在我非常爽,就是当下的最有解.假设如下是我所拥有的零钱value是面值,count是对应面值的数量.所以当我们要求速度或者只顾当前的最优解,那么我们可以考虑贪心算法.一般我们会设置手头面值最大的值来进行换取,不够再用小面值的凑.但是顾局大全就不可以了,所谓目光短浅,就是如此.那么我是从后往前来进行的遍历先是面值最大的.但是我用这种情况的时候,就不是最优解了.2024年8月17日19:59:34。就是我看眼前的我怎么舒服怎么来.原创 2024-08-17 20:00:16 · 512 阅读 · 1 评论 -
【数据结构与算法】选择排序
我们可以每次从里面选择最大的,放在最后面,继续选剩下的最大的放在刚刚放在最后面的前面一个.也可以按i的次序来假设为最小值想后面的比较,这样就不用担心重复比较了.但是我们想要一个数组就完成的话,那就需要进行元素的交换就可以了.假设我们想要将此排序按从小到大,那么我们可以怎么排呢?每次选择最小的放在前面也是同样的道理.假设最后一个为最小值往前比较.依次排放就完成排序了.原创 2024-08-18 10:58:15 · 240 阅读 · 0 评论 -
【数据结构与算法】冒泡排序
这里有个问题,就是明明我们两轮就比较出来了,但是为了其他的情况,我们还是要继续比较,浪费资源,那么有没有什么办法呢?所以我们可以设置一个排好序的标志,如果这一轮有交换就说明没有排好序,还需要继续.冒泡排序的原理是,将两两进行比较,如果前面较大的我们就进行交换到后面.然后再对交换后的这个和下一个进行比较,一轮过后,最大值就交换到最后了.如果这一轮都没有进行交换,那么我们就可以退出了,证明已经排好了.那就是虽然两两比较,但是没有交换了嘛.2024年8月18日14:47:19。原创 2024-08-18 14:48:06 · 382 阅读 · 0 评论 -
【数据结构与算法】插入排序
将第一个元素当成已经是有顺序的,然后后面的元素与之比较插入到在顺序中的位置.当然这个过程是要设计元素的移动的,这样才有空间来进行插入.2024年8月18日15:57:15。原创 2024-08-18 15:58:08 · 277 阅读 · 0 评论 -
【数据结构与算法】希尔排序
上节课我们讲了插入排序,但是插入排序有个缺点,就是需要移动数据,如果刚好最后面是最小的值,那么就需要乾坤大罗伊了.三重循环,内两层循环和插入排序一样,只不过不是1了,是gap这个增量参与计算比较.本质也是插入排序,只不过是就原有的数组进行多次分组然后再进行插入排序.为了减少移动的次数,在1959年,希尔老帅哥就创建了一种排序.最后再完整的来一次插入排序,那么元素移动的次数就会大大的减少.2024年8月19日10:42:09。最外层就是来分组的.原创 2024-08-19 10:42:47 · 294 阅读 · 0 评论 -
【数据结构与算法】归并排序
有一种情况就是一边已经加入完了,但是还有一边还有没有加入的,所以我们需要添加进数组,最后在拷贝到原数组.我们可以拆分为有序的,就是一直拆为只有1个元素,1个元素必定有序,然后可以采用归并.将一个数组分为两段,那边的值小就加入到新数组中,直到一边已经加完了.我们也已经注意到了,上面的是有序的两端合并排序,那如果无序的呢?2024年8月19日16:10:18。如何将这两个数组排序?原创 2024-08-19 16:11:50 · 659 阅读 · 6 评论 -
【数据结构与算法】快速排序
基准数就已经在有序的位置上了,开始两边分而治之.low和high就是数组的下标的最左边和最右边.分别左右两边依次比较,排好的就下次就不比较了.2024年8月20日10:29:49。不停的将基准数的两边进行快速排序.直到i==j说明比较完毕.选择最小的数为基准数.原创 2024-08-20 10:30:29 · 641 阅读 · 5 评论 -
【数据结构与算法】二分查找
如果目标值等于中间的值,我们就返回这个下标,大于的话,左边的起始位置改变,小于的话,右边的位置改到中间位置的前一个.一直循环,直到left不小于right时.在void*类型的数组中找目标元素的位置用的是指针加步长.就是字节的长度.上次在分治法里面我们用的递归实现,现在我们就普通的方法来实现.就是这个原理,跟中间的比的话,每次都可以排除一半.这里我们写了int类型和char类型的比较.返回-1的就是没找到,其他的都是下标的位置.为了能适应多种类型的查找,我们用到了。2024年8月20日15:57:16。原创 2024-08-20 15:58:26 · 668 阅读 · 6 评论