数据结构与算法
文章平均质量分 78
常见的数据结构
怡晗★
有在努力的小coder
展开
-
C++分析二叉搜索树
首先确定待删除的节点是左孩子为空还是右孩子为空,以左孩子为空为例,如果待删除节点的左孩子为空,则链接时,需要将待删除节点的父亲节点链接到待删除节点的右孩子,链接完成后删除节点,跳出循环即可。考虑完上述两种情况后,还有一种情况,如果只有一个根节点时,只考虑上面两种情况会导致程序崩溃,只有一个根节点时,此时根节点的左右子树均为空,属于第一种情况,删除之前需要让根指向其左孩子或者右孩子。节点有一个孩子节点,删除节点时需要先找到该节点的父亲节点,由该父亲节点链接其孩子节点,例如图中的14节点。原创 2024-07-16 19:31:22 · 923 阅读 · 0 评论 -
(3)滑动窗口算法练习:最长连续1的个数Ⅲ
本题的暴力解法为:枚举子数组+记录0的个数,在暴力解法的基础上,对暴力解法进行优化,在枚举的过程中,定义两个指针。时,此时代表合法区间已经出现,因为k到达上限,所以不可以继续向后移动。回到了上一个合法区间的最后一个元素的位置,如果该位置的数值为0,则。移动到上一个合法区间的最后一个元素的位置,如果为0,则计数器减1。移动到上一次满足条件的区间的最后一个元素的位置,计数器需要减1,代表这个位置已经翻转过一次,还有。个,接下来需要枚举下一个区间,那么。加1,代表0出现1次,便于后面与。原创 2024-07-10 22:28:56 · 424 阅读 · 0 评论 -
(2)滑动窗口算法练习:无重复字符的最长子串
的取值只会出现英文字母、数字、符号和空格,所以只需要定义一个长度为128的数组即可,对应的下标即为对应字符的ASCII码值。就停止移动,所以当哈希表数组字符ASCII值下标对应的元素不为0即代表重复,作为判断条件。出窗口:出窗口则意味着已经在哈希表中的元素需要离开哈希表,并让。对于哈希表的处理,不需要使用库中的结构,因为题目中给出了结果。指针向右移动,直到遇到一个已经出现的字符停止,此时。,请你找出其中不含有重复字符的最长子串的长度。中不存在已经重复的字符,因为已经跳过了重复的字符。原创 2024-07-09 22:40:52 · 709 阅读 · 0 评论 -
(1)滑动窗口算法介绍与练习:长度最小的子数组
所谓滑动窗口,即为同向双指针移动过程中形成的间隔区域,并且这两个指针在移动的过程中不会回退定义窗口两端指针left和right进入窗口判断离开窗口循环2、3和4步。原创 2024-07-08 21:39:07 · 946 阅读 · 0 评论 -
(8)双指针练习:四数之和
本题与三数之和的思路基本一致,即排序+双指针算法,根据表达式。注意本题有数据溢出的情况。,再通过双指针算法得到。,所以先确定两个基数。原创 2024-05-21 13:03:15 · 266 阅读 · 0 评论 -
(7)双指针练习:三数之和
进行去重,但是这个思路的时间复杂度为O(N3)导致代码超时。在暴力的基础上可以考虑使用双指针算法对暴力枚举和。因为双指针可以取出连个数值,所以需要一层循环用于固定第三个数作为基数,假设为。本题如果直接使用暴力解法,那么可以考虑思路:排序+暴力枚举+使用。而因为数组已经经过了排序,所以可以参考。,因为三个数计算的结果为0,所以有。,而两个指针计算的和为。移动到等式的右侧后变为。,所以可以考虑定义一个。原创 2024-05-20 15:55:51 · 396 阅读 · 0 评论 -
(6)双指针练习:查找总价格为目标值的两个商品
进行比较,相等时返回两个加数即可,但是这种方法会超时,所以考虑其他方法。本题直观解法是暴力枚举,使用两层。指针从右向左遍历,第一种情况如果。指针从左向右遍历,一个。的数值大,所以可能存在。的数值小,所以可能存在。数组有序后,定义一个。原创 2024-05-19 13:55:52 · 170 阅读 · 0 评论 -
(5)双指针练习:有效三角形个数
对于其余两种情况来说,因为c已经大于b和a,那么c + b或者c + a均会大于其余两边。对于排序之后的数组来说可以很容易确定最大值的位置,将最大值作为第三边后就只需要判断其余两边之和是否大于这个最大值即可。在判断三个整数是否可以构成三角形时,假设三边分别为a、b和c,此时需要判断任意两边之和是否大于第三边,即。因为数组已经进行了排序,此时可以采用二分算法进行求解,但是使用双指针的算法会更优。),另外在判断是否能构成三角形时使用的三次判断,那么时间复杂度准确来说是O(本题最直观的解法就是通过三层。原创 2024-05-18 14:52:55 · 686 阅读 · 0 评论 -
(3)双指针练习:快乐数
即810,那么说明在计算快乐数时,所有的给定数值最后的结果都会出现在[1, 810]这个范围中(鸽子巢),既然如此,根据鸽巢原理,假设数字变化的次数为811(鸽子),因为范围固定,那么最后一个数值肯定会再一次出现在[1, 810]这个范围中,此时就会出现结果循环,所以一定会出现至少一个数值是重复出现导致成环,所以不存在因为数值无限增大而导致死循环。鸽巢原理:有n个鸽子巢,有n+1个鸽子,如果将鸽子放入鸽子巢中,那么至少会存在一个鸽子巢中的鸽子数量大于或等于1。原创 2024-05-16 12:30:09 · 1362 阅读 · 0 评论 -
(4)双指针练习:盛最多水的容器
根据上面的规律可以得出,因为遍历数组的过程中一定会出现width在减小的情况,为了使最后的v不变或者变大,只有改变height,如果出现一侧高度比另一侧高度小时,为了使height增大,需要移动小的一侧高度从而找到更高的高度,此时可以考虑使用双指针算法,左指针。本题最直观的解法就是暴力枚举,通过外层for循环枚举其中一条高,再固定内层for循环枚举另一条高,求出体积的最大值即可,但是直接使用暴力枚举的时间复杂度为O(N2)会出现超时。因为两个指针从两侧向中间移动确定高度,所以时间复杂度为O(N)原创 2024-05-17 14:24:26 · 317 阅读 · 0 评论 -
(2)双指针练习:复写零
对于双指针算法来说,有两种实现方式,第一种是异地复写,即开辟一个新空间,基本思路为遇到非0数字复写一次,遇到数字0复写两次,但是这个算法的空间复杂度为O(N),所以考虑原地复写。暴力的方法很简单,因为是复写,所以只需要遇到0先将0位置后面的数据进行挪动覆盖,但是注意要从尾部开始挪动,挪动完毕后在当前位置的下一个位置插入一个数字0,让指针走两步。指向的位置已经超出了数组的范围,如果此时在。所指向的位置即为最后一个待复写的元素,而。当指向的待复写元素是0时,那么此时。原创 2024-05-15 22:54:05 · 692 阅读 · 0 评论 -
(1)双指针算法介绍与练习:移动零
双指针算法常见于数组和双向链表的题型在数组中,双指针中的指针代表数组元素的下标,而不是真正的指针类型变量在双向链表中,双指针中的指针即为真正意义上的指针,该指针一般是双向链表节点类型的指针对撞指针:从结构的两端开始向中间移动,一般存在两种情况:代表两个指针指向的时同一个位置:代表连个指针已经相遇过一次,相遇的下一次形成交错快慢指针:所谓快慢指针即为一个指针走得快,一个指针走得慢快慢指针一般的思路是:慢指针走一步,快指针走两步。原创 2024-05-15 19:29:28 · 612 阅读 · 0 评论 -
中缀表达式转后缀表达式
一个操作符的优先级不是由该操作符本身决定的,而应该是由相邻的操作符彼此直接优先级等级决定的。上面的思路为基本的思路,但是存在一种优化思路,因为不考虑括号时,一共就4个操作符,而这四个操作符只存在。后面的操作符优先级,但是由于此时走到了算式结尾,所以现在可以确定。,但是此时并不能进行计算,需要确定后面紧接的操作符是否比当前的。,当计算时根据从左往右计算的规则,第一个看到的操作符是。号,但是现在也不可以进行计算,因为。优先级高,所以当前元素为。的操作符的优先级是否比。的操作符优先级的确比。原创 2024-04-28 13:04:31 · 351 阅读 · 0 评论 -
C语言分析基础排序算法——计数排序
则不能考虑开辟最大元素+1个元素的空间,因为此时总数据个数小于数组的总长度,造成了空间浪费,可以考虑找出数组中的最大值和最小值,取其差值+1开辟数组,并且此时对应的下标应该是两数之差。通过上面的思路解析,很明显计数排序的局限性很大,需要排序的数据必须非常集中,否则不容易计数。计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。计数排序的时间复杂度为O(max(N,)),空间复杂度为O(原创 2024-03-13 23:03:57 · 544 阅读 · 2 评论 -
C语言分析基础排序算法——归并排序
如果数据的个数特别大时,再让数据一直递归到只有一个数据的一层时会导致递归太深从而栈溢出,可以考虑在只有十个数据递归时采用其他排序算法进行优化,此处可以采用直接插入排序,因为每进行一次递归,数据会被分成两部分,所以当递归到只有十个数据时时,数据个数就已经比较小了。直接对所有区间进行修正,将越界的区间修正成左区间大于右区间的不存在区间,此时不存在的区间将不会进入循环,而存在的区间也是有效区间,直接整体拷贝即可。但是上面的方法存在一个问题,如果数组的数据不是2的次方个,那么将无法完成排序,存在越界问题。原创 2024-03-13 22:02:54 · 860 阅读 · 0 评论 -
C语言分析基础排序算法——交换排序
在快速排序优化部分,采用三数取中的思路对快速排序有大量重复数据或者有序情况下进行优化,所谓三数取中,即第一个元素的位置和最后一个元素的位置加和取一半的数值在数据中的位置,但是此时需要注意的是。所在的数值以及相遇位置的数值,完成第一趟排序,接着进行左边部分的排序,方法如同第一趟排序,左边排序完毕后进行右边部分的排序,方法如同第二趟排序,直到最后全部排序完成后为止。接着进行左边部分的排序,方法如同第一趟排序,左边排序完毕后进行右边部分的排序,方法如同第二趟排序,直到最后全部排序完成后为止。原创 2024-03-11 12:50:57 · 1632 阅读 · 1 评论 -
C语言分析基础排序算法——选择排序
选择排序的基本思路是,定义两个区间指针begin和end,遍历数组中的每一个数据找出最大的数据的下标和最小的数据的下标,之后与。堆排序算法实现与分析见下方的博客文章。堆排序算法及分析-CSDN博客。指针分别交换小数据与。的数值,具体思路如下。原创 2024-03-08 17:35:32 · 480 阅读 · 0 评论 -
C语言分析基础排序算法——插入排序
第二个问题,如果将预排序和最后的插入排序分开写,那么需要写五个循环,三层循环解决预排序,两层循环解决最后的插入排序,所以可以考虑将预排序与直接插入排序放在一起,达到在同一个循环中解决问题。而改进后的思路与原来的思路对比:原来的思路是先排一组,排完一组后再排第二组,而改进后的思路是遇到i当前位置是哪一组的就排哪一组的数据,但是需要注意的是,当前的。组,对各组进行插入排序,这一步被称作预排序,接着再使用直接插入排序对整体再进行一次排序,具体过程如下。决定了分组的数量,也间接决定了最大值走到最后需要的次数,当。原创 2024-03-08 16:34:11 · 1120 阅读 · 0 评论 -
C语言实现基础数据结构——二叉树(二叉树基础部分)
/定义二叉树的数据类型//定义二叉树结构}BTN;原创 2024-03-06 23:28:14 · 1041 阅读 · 0 评论 -
堆与TopK问题分析
此处的主要思路是:因为前K个最大数值肯定比其余数值都大,但是不需要保证在第一步中一定取出的是最大的数值,所以每一次遇到一个属于前K个最大数值的数据时肯定会顶替掉根节点进入小堆重新排列,此过程一直持续到最后没有数据比根节点(前K个最大的数值中的最小值)的数据还要大的时候就结束。第一步先抽取数据中的前K个值建立一个小堆,因为小堆的结构满足最小的数值一定在根节点,而比根节点大的数值一定会排在根节点的后面。第二步再将剩余的N-K个数值依次与小堆的根节点数据进行比较,如果比根节点大就覆盖根节点并恢复成小堆。原创 2024-03-02 12:12:41 · 371 阅读 · 1 评论 -
堆排序算法及分析
上面的思路是建立在已经实现了堆的数据结构以及相应功能,如果不存在该结构,则无法直接使用该排序,过程相对繁琐,所以可以考虑单独抽出向上调整算法和向下调整算法直接进行排序算法的实现,因为从排序开始到排序结束,只会用到向上调整算法实现数组数据到堆的构建,以及向下调整算法对数据进行重新整理,而控制台能看到升序的数值是因为在每次删除数据之前都进行了一次根节点数据的取出,在小堆中,根节点数据为最小的数值,所以最后实现一个升序的效果。所谓堆排序,就是通过堆的插入和删除的特点实现对数组内的数据进行排序。原创 2024-03-01 23:26:04 · 961 阅读 · 1 评论 -
C语言实现基本数据结构——堆
/ 定义堆中存储的数据的数据类型// 堆的结构设计// 存储数据部分int size;// 堆中的有效数据个数// 堆的容量大小}HP;原创 2024-02-28 21:50:08 · 789 阅读 · 0 评论 -
树的基本概念和结构
每棵子树的根结点有且只有一个前驱,可以有0个或多个后继,因此,树是递归定义(根节点(A)→子节点(B)→父节点(B)→子节点(E)→父节点(E)→叶子节点(J))的。节点的层次:从根节点开始,根为第一层,根的子节点为第二层,以此类推(节点的层次建议从1开始计算)父节点(或双亲节点):若一个节点含有子节点,则该节点为其子节点的父节点。根节点:根节点为树的第一个节点,该节点没有前驱节点(即没有父亲节点)子节点(或孩子节点):一个节点含有的子树的父节点称为该节点的子节点。叶节点(或终端节点):度为0的节点。原创 2024-02-26 23:00:11 · 415 阅读 · 0 评论 -
C语言实现基本数据结构——队列
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。注意队列不同于栈,出队列顺序和入队列顺序必定刚好相反(即满足先进先出)入队列:进行插入操作的一端称为队尾。出队列:进行删除操作的一端称为队头。原创 2024-02-23 21:22:30 · 498 阅读 · 3 评论 -
C语言实现基础数据结构——栈
在初始化过程中注意top的初始值设置为0代表栈内数据的下一个位置,因为初始化栈代表栈内没有元素,如果用0代表栈内数据的当前位置,那么需要考虑该元素从何而来,既然没有数据,说明当前栈顶指针指向没有数据的位置,而数组下标为0代表第一个元素的位置,没有元素就不可能有第一个元素的位置,所以此时下标为0代表下一个元素的位置,此时说明栈内没有元素,但是准备在下一个位置(第一个元素)的位置添加数据。注意在栈中数据出栈的顺序不一定和入栈的顺序相同,当数据入栈后又出栈不影响下一个数据的入栈顺序。出栈:栈的删除操作叫做出栈。原创 2024-02-22 22:25:15 · 968 阅读 · 0 评论 -
C语言实现基础数据结构——顺序表
基本思路:以删除位置(第一个数值位置为1)为标准,将删除位置之后的数值覆盖删除位置的数值,并且有效数值前移。基本思路:以插入位置(第一个数值位置为1)为标准,将插入位置后面的内容向后移动,并且有效数值变量后移。静态顺序表空间给少了不够用,给多了造成空间浪费,实际使用顺序表更多使用动态顺序表。顺序表的底层结构是数组,对数组的封装,实现了常用的增删改查等接口。基本思路:将有效数值变量前移达到“看不见即删除”的效果。基本思路:将后面的值一一往前覆盖,并且有效数值变量前移。数组的大小固定的顺序表。原创 2024-01-29 18:46:25 · 377 阅读 · 0 评论 -
C语言实现基础数据结构——链表
链表是线性表中的其中一种结构,链表在物理存储结构上是非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。在链表中,每一个存储空间都是独立申请的(需要添加数据时申请),也被称为节点(结点)在双向链表中,存在头结点,即默认有一个节点,但是该节点中不存储有效数据,只存储指向上一个节点和下一个节点的地址。在双向链表中,空链表的含义是除了头结点以外没有其他任何节点(即没有存储有效数据的节点)基于链表实现顺序表学习到的通讯录项目。在双向链表中,头结点是不可以删除的。链表实现时需要熟悉的三个。原创 2024-01-29 18:54:50 · 1105 阅读 · 0 评论 -
数据结构中的时间复杂度和空间复杂度基础
在进行第一次查找过程中,数组元素个数为10,第二次查找数组元素个数为5,第三次查找数组元素个数为2,即元素个数n与代码执行次数x成对数关系,每一次少一半,也就是除以2,即多少次折半对应多少个元素,即 = n,以上面的数组为例,当前10个元素,则有等式 = 10,故x≈3,最坏情况下三次才能找到那么x对应的就是代码执行次数,即时间复杂度,故二分查找的时间复杂度为O()(注意此处的N为元素个数)但是,时间复杂度计算的是一个估计值,也就是说,我们不需要完全准确地将代码执行次数计算出来,对于上面的表达式,由于。原创 2024-02-03 22:30:18 · 1213 阅读 · 2 评论