数据结构与算法
C++及Python中的数据结构与算法
周一写bug,bug改一周
这个作者很懒,什么都没留下…
展开
-
数据结构与算法——红黑树
目录平衡二叉查找树红黑树平衡二叉查找树平衡二叉查找树中“平衡”的意思,其实就是让整棵树左右看起来比较“对称”、比较“平衡”,不要出现左子树很高、右子树很矮的情况。这样就能让整棵树的高度相对来说低一些,相应的插入、删除、查找等操作的效率高一些。红黑树红黑树的英文是“Red-Black Tree”红黑树的定义:根节点是黑色的;每个叶子节点都是黑色的空节点(NIL),也就是说,叶子节点不存储数据;任何相邻的节点都不能同时为红色,也就是说,红色节点是被黑色节点隔开的;每个节点,从该节点到达其可达原创 2020-11-10 14:49:44 · 230 阅读 · 0 评论 -
数据结构与算法——二叉树
目录树的概念二叉树二叉树遍历树的概念父节点、子节点、兄弟节点、根节点、叶子节点、叶节点。高度、深度、层二叉树满二叉树: 编号 2 的二叉树中,叶子节点全都在最底层,除了叶子节点之外,每个节点都有左右两个子节点,这种二叉树就叫做满二叉树。完全二叉树: 叶子节点都在最底下两层,最后一层的叶子节点都靠左排列,并且除了最后一层,其他层的节点个数都要达到最大,这种二叉树叫做完全二叉树。二叉树的储存方式:一种是基于指针或者引用的二叉链式存储法,一种是基于数组的顺序存储法。二叉树遍历前序遍历、中原创 2020-11-10 14:49:20 · 197 阅读 · 0 评论 -
数据结构与算法——哈希算法
目录什么是hash算法应用一:安全加密应用二:唯一标识应用三:数据校验应用四:散列函数应用五:负载均衡应用五:数据分片如何统计“搜索关键词”出现的次数?如何快速判断图片是否在图库中?应用七:分布式存储什么是hash算法将任意长度的二进制值串映射为固定长度的二进制值串,这个映射的规则就是哈希算法,而通过原始数据映射之后得到的二进制值串就是哈希值。hash算法满足以下几点要求从哈希值不能反向推导出原始数据(所以哈希算法也叫单向哈希算法);对输入数据非常敏感,哪怕原始数据只修改了一个 Bit,最后得到原创 2020-11-10 14:48:56 · 345 阅读 · 0 评论 -
数据结构与算法——散列表
这里写目录标题散列表散列函数散列冲突开放寻址法链表法动态扩容如何避免低效扩容Java 中的 HashMap初始大小装载因子和动态扩容散列冲突的解决办法散列函数散列表散列表用的是数组支持按照下标随机访问数据的特性,所以散列表其实就是数组的一种扩展,由数组演化而来。可以说,如果没有数组,就没有散列表。把编号转化为数组下标的映射方法就叫作散列函数(或“Hash 函数”“哈希函数”),而散列函数计算得到的值就叫作散列值(或“Hash 值”“哈希值”)。散列表两个核心问题是散列函数设计和散列冲突解决散列函原创 2020-11-10 14:48:21 · 267 阅读 · 0 评论 -
数据结构与算法——跳表
目录如何理解“跳表”用跳表查询到底有多快跳表是不是很浪费内存高效的插入和删除跳表索引的动态更新如何理解“跳表”单链表对链表建立一级“索引”比如 16。我们可以先在索引层遍历,当遍历到索引层中值为 13 的结点时,我们发现下一个结点是 17,那要查找的结点 16 肯定就在这两个结点之间。然后我们通过索引层结点的 down 指针,下降到原始链表这一层,继续遍历。这个时候,我们只需要再遍历 2 个结点,就可以找到值等于 16 的这个结点了。这样,原来如果要查找 16,需要遍历 10 个结点,现在只需要原创 2020-11-10 14:48:03 · 182 阅读 · 0 评论 -
数据结构与算法——排序(桶排序、计数和基数)
目录桶排序时间复杂度分析桶排序首先,我们来看桶排序。桶排序,顾名思义,会用到“桶”,核心思想是将要排序的数据分到几个有序的桶里,每个桶里的数据再单独进行排序。 桶内排完序之后,再把每个桶里的数据按照顺序依次取出,组成的序列就是有序的了。时间复杂度分析如果要排序的数据有 n 个,我们把它们均匀地划分到 m 个桶内,每个桶里就有 k=n/m 个元素。每个桶内部使用快速排序,时间复杂度为 O(k * logk)。m 个桶排序的时间复杂度就是 O(m * k * logk),因为 k=n/m,所以整个桶排原创 2020-11-10 14:47:44 · 372 阅读 · 0 评论 -
数据结构与算法——排序(归并和快排)
目录归并排序原理归并排序的代码实现归并排序性能分析快速排序原理快速排序的代码实现快速排序的性能分析归并排序和快速排序的区别归并排序原理归并排序的核心思想还是蛮简单的。如果要排序一个数组,我们先把数组从中间分成前后两部分,然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就都有序了。归并排序使用的就是分治思想。 分治,顾名思义,就是分而治之,将一个大问题分解成小的子问题来解决。小的子问题解决了,大问题也就解决了。归并排序的代码实现递推公式:merge_sort(p…r) = m原创 2020-11-10 14:47:24 · 309 阅读 · 0 评论 -
数据结构与算法——排序(冒泡、插入和选择)
目录如何分析一个排序算法算法的执行效率排序算法的内存消耗排序的稳定性冒泡排序插入排序选择排序总结如何分析一个排序算法算法的执行效率最好情况、最坏情况、平均情况时间复杂度时间复杂度的系数、常数 、低阶比较次数和交换(或移动)次数排序算法的内存消耗我们前面讲过,算法的内存消耗可以通过空间复杂度来衡量,排序算法也不例外。不过,针对排序算法的空间复杂度,我们还引入了一个新的概念,原地排序(Sorted in place)。原地排序算法,就是特指空间复杂度是 O(1) 的排序算法。我们今天讲的三种原创 2020-10-20 14:20:55 · 257 阅读 · 0 评论 -
数据结构与算法——队列
目录什么是队列队列的实现基于数组的队列实现基于链表的队列实现循环链表阻塞队列和并发队列问题什么是队列队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。先进者先出,这就是典型的“队列”。队列的实现基于数组的队列实现跟栈一样,队列可以用数组来实现,也可以用链表来实现。用数组实现的栈叫作顺序栈,用链表实现的栈叫作链式栈。同样,用数组实现的队列原创 2020-10-19 09:59:46 · 342 阅读 · 0 评论 -
平衡树、B树和B+树
目录树的深度、高度、层数和度平衡二叉树性质插入操作B树性质查找、插入、删除B+树性质树的深度、高度、层数和度从节点角度高度的定义: 从结点x向下到某个叶结点最长简单路径中边的条数。K节点在树的底层,是一个叶子节点,则一般定义为K的高度在最低为1,以此类推,O的高度也是为1,P的节点也是为1。M节点是叶子节点O的父节点,从下往上数,M节点高度为2。那么G节点的高度是多少呢?从G-L的高度为2,从G-M-O节点高度为3,到底G节点高度为多少呢,正确答案是3深度的定义: 从根节点往下唯一路径的长。列原创 2020-10-17 14:49:55 · 388 阅读 · 0 评论 -
数据结构与算法——栈
目录栈的原理栈的实现支持动态扩容的顺序栈栈在函数调用中的应用栈的原理栈是一种线性表,仅在表尾进行插入和删除的线性表,称为栈顶。是按照先进后出的原则储存数据,后进者先出,先进者后出,这就是典型的“栈”结构。当某个数据集合只涉及在一端插入和删除数据, 并且满足后进先出、先进后出的特性,我们就应该首选“栈”这种数据结构。栈的实现用数组实现的栈,我们叫作顺序栈,用链表实现的栈,我们叫作链式栈。数组栈的实现代码// 基于数组实现的顺序栈public class ArrayStack { priv原创 2020-10-17 09:54:01 · 181 阅读 · 0 评论 -
数据结构与算法——链表(下)
目录链表的五个技巧理解指针和引用含义警惕指针丢失和内存泄漏利用哨兵简化难度留意边界条件的处理链表典型题链表的五个技巧理解指针和引用含义在编写链表代码的时候,我们经常会有这样的代码:p->next=q。这行代码是说,p 结点中的 next 指针存储了 q 结点的内存地址。还有一个更复杂的,也是我们写链表代码经常会用到的:p->next=p->next->next。这行代码表示,p 结点的 next 指针存储了 p 结点的下下一个结点的内存地址。将某个变量赋值给指针,实际上就是原创 2020-10-16 10:09:45 · 179 阅读 · 0 评论 -
数据结构与算法——链表(上)
目录问题引入链表的结构查找、插入和删除操作时间、空间的设计思想数组和链表的比较问题引入如何用链表来实现 LRU 缓存淘汰策略呢?缓存的大小有限,当缓存被用满时,哪些数据应该被清理出去,哪些数据应该被保留?这就需要缓存淘汰策略来决定。常见的策略有三种:先进先出策略 FIFO(First In,First Out)、最少使用策略 LFU(Least Frequently Used)、最近最少使用策略 LRU(Least Recently Used)。设计思路:我们维护一个有序单链表,越靠近链表尾部的结点原创 2020-10-15 10:15:03 · 234 阅读 · 0 评论 -
数据结构与算法——数组
目录什么是数组数组的寻址插入和删除操作数组越界问题容器是否能代替数组什么是数组数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据。第一是线性表(Linear List)。顾名思义,线性表就是数据排成像一条线一样的结构。每个线性表上的数据最多只有前和后两个方向。其实除了数组,链表、队列、栈等也是线性表结构。而与它相对立的概念是非线性表,比如二叉树、堆、图等。之所以叫非线性,是因为,在非线性表中,数据之间并不是简单的前后关系。第二个是连续的内存空间和相同类原创 2020-10-15 09:44:52 · 264 阅读 · 0 评论 -
算法复杂度分析——时间复杂度(下)
目录最好情况时间复杂度(best case time complexity)、最坏情况时间复杂度(worst case time complexity)、平均情况时间复杂度(average case time complexity)、均摊时间复杂度(amortized time complexity)最好情况时间复杂度: 在最理想的情况下,执行这段代码的时间复杂度。在最理想的情况下,要查找的变量 x 正好是数组的第一个元素,这个时候对应的时间复杂度就是最好情况时间复杂度。最坏情况时间复杂度: 在最糟糕原创 2020-10-14 16:24:02 · 287 阅读 · 0 评论 -
后序遍历及其算法-基于栈的遍历
后序遍历及其算法-基于栈的遍历1.后序遍历算法原理讲解二叉树后序遍历示意图若树为空,则空操作返回。否则,从左到右先叶子后节点的方式遍历访问左右子树,最后访问根节点。(左右中)逆时针型(左右 中)算法思路从根节点开始,每次迭代弹出当前栈顶元素,并将其孩子节点压入栈中,先压右节点再压左节点。在这个算法中,输出到最终结果的顺序按照 Top->Bottom 和 Left->Righ...原创 2020-09-05 17:32:41 · 1111 阅读 · 0 评论 -
中序遍历及其算法-基于栈的遍历
中序遍历及其算法-基于栈的遍历1.中序遍历算法原理讲解二叉树中序遍历示意图若树为空,则空操作返回。否则,从根节点开始(注意并不是先访问根节点),中序遍历根节点的左子树,然后是(访问根节点,最后中序遍历根节点的右子树。(M)型,(左中)算法思路从根节点开始,每次迭代弹出当前栈顶元素,并将其孩子节点压入栈中,先压右节点再压左节点。在这个算法中,输出到最终结果的顺序按照 Top->Bo...原创 2020-09-05 17:32:15 · 2323 阅读 · 0 评论 -
前序遍历及其算法-基于栈的遍历
前序遍历及其算法-基于栈的遍历1.前序遍历算法原理讲解二叉树前序遍历示意图算法思路从根节点开始,每次迭代弹出当前栈顶元素,并将其孩子节点压入栈中,先压右节点再压左节点。在这个算法中,输出到最终结果的顺序按照 Top->Bottom 和 Left->Right,符合前序遍历的顺序。2.基于栈的算法实现定义树的结构体struct TreeNode{ int va...原创 2020-09-05 17:31:48 · 1215 阅读 · 0 评论 -
哨兵原理及适用场景
这里写目录标题1哨兵的技巧1哨兵的技巧使用哨兵,避免特殊情况的讨论其它作用:单链表虚拟头结点,插入排序原创 2020-09-05 17:27:52 · 196 阅读 · 0 评论 -
单调栈的应用和案例详解
目录1 单调栈2 使用场景1 单调栈单调栈首先是栈,是栈的应用栈内元素维持了单调性的应用场景单调递增(不减)栈可以找到左边第一个比当前栈元素小(包含等于)的元素;单调递减(不增)栈可以找到左边第一个比当前栈元素小(包含等于)的元素2 使用场景在使用单调栈的场景下,都能用暴力法解决。暴力解法具有较高的时间复杂度,而利用单调栈能减低时间复杂度。单调栈最重要的是清楚什么时候入栈和出栈。具体案例见以下力扣题库:第42题:接雨水第84题:柱状图的最大面积第739题:每日温度第496题:原创 2020-09-03 09:00:46 · 222 阅读 · 0 评论 -
深度优先搜索算法(DFS)原理及示例详解
目录1 算法原理2 基本思路980.不同路径题目描述输入输出示例直观思路代码实现1 算法原理事实上,深度优先搜索属于图算法的一种,英文缩写为DFS即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次.举例说明之:下图是一个无向图,如果我们从A点发起深度优先搜索(以下的访问次序并不是唯一的,第二个点既可以是B也可以是C,D),则我们可能得到如下的一个访问过程:A->B->E(没有路了!回溯到A)->C->F-原创 2020-08-31 08:20:14 · 19139 阅读 · 0 评论 -
回溯算法——算法原理及八皇后问题图解分析(超详细)
1回溯算法原理回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。许多复杂的,规模较大的问题都可以使用回溯法,有“通用解题方法”的美称。2例题讲解——八皇后问题2.1题目描述设计一种算法,打印 N 皇后在 N ×原创 2020-08-26 15:55:18 · 5137 阅读 · 1 评论 -
动态规划算法详解——三大基本要素、解题步骤、算法优化和例题详解
目录1动态规划思想2适用场景3例题分析3.1示例1:42.接雨水1动态规划思想2适用场景3例题分析3.1示例1:42.接雨水题目描述给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。输入输出描述输入: [0,1,0,2,1,0,1,3,2,1,2,1]输出: 6图解模型直观思想在暴力方法中,我原创 2020-08-25 15:53:09 · 16932 阅读 · 0 评论 -
递归算法详解——递归算法的三要素以及例题分析
目录1递归的三要素1.1明确函数的功能1.2递归的结束条件1.3函数的等价关系2递归案例递归算法(英语:recursion algorithm)是指一种通过重复将问题分解为同类的子问题而解决问题的方法。1递归的三要素递归的三要素明确函数的功能递归的结束条件函数的等价关系接下来利用nnn阶乘来讲解这三个条件任何大于等于1 的自然数nnn阶乘表示方法:n!=n×(n−1)!(n>1)0!=1(n=0)n!=n \times(n-1)! \quad (n > 1) \\ 0! =原创 2020-08-24 20:05:24 · 5053 阅读 · 0 评论 -
题型总结——双指针算法全部模型(持续更新)
目录1双指针概念及类型2同向双指针2.1示例一:26.删除排序数组中的重复元素3异向双指针3.1类型一:二分查找3.2示例1:42.接雨水4快慢指针5类似双指针模型5.1两个指针分别在两个数组中6滑动窗口1双指针概念及类型通常用在线性的数据结构中,比如链表和数组。指针其实就是数据的索引或者链表的结点。两个指针朝着左右两个方向移动,直到满足搜索条件。双指针可分为同向双指针、异向双指针、快慢指针、滑动窗口。根据需求选择双指针的模型,比如删除数组或链表中重复的元素,同向双指针(线性表前提是有序的);原创 2020-08-24 14:38:21 · 567 阅读 · 0 评论 -
题型总结——栈的应用
目录1栈的原理2栈的适用场景3例题分析3.1有效的括号匹配1栈的原理2栈的适用场景3例题分析3.1有效的括号匹配示例1:20.有效的括号示例2:42.接雨水题目描述给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。输入输出描述输入: [0,1,0,2,1,0,1,3,2,1,2,1]输出: 6直原创 2020-08-24 09:42:03 · 294 阅读 · 0 评论 -
题型总结——二维数组(矩阵)之逆逆时针输出、查找
目录1二维数组与矩阵的联系2逆时针输出二维数组元素2.1模拟法算法复杂度分析2.2按层模拟算法复杂度分析3查找指定的元素3.1暴力法3.1.1复杂度分析3.2 线性查找3.2.1复杂度分析说明: 关于二维数组的题型总结会持续更新。1二维数组与矩阵的联系数组一般是指数据结构,矩阵是数学概念。在逻辑上一般把二维数组看成是一个具有行和列的矩阵。把矩阵看做列向量得出矩阵的维数,比如四行三列矩阵可以看成三个列向量表示的四维空间。m×mm \times mm×m的矩阵可以看做是mmm阶方阵2逆时针输出二维数原创 2020-08-23 11:01:01 · 1648 阅读 · 0 评论 -
数据结构与算法——二分查找
目录1适用场景2算法流程3算法复杂度分析3.1时间复杂度分析4LeetCode题型总结1适用场景数据结构必须先排好序,可以在数据规模的对数时间复杂度内完成查找二分查找要求线性表具有有随机访问的特点(例如数组),也要求线性表能够根据中间元素的特点推测它两侧元素的性质2算法流程如果目标值等于中间元素,则找到目标值。如果目标值较小,继续在左侧搜索。如果目标值较大,则继续在右侧搜索。**注意:**在计算左右端点的中点时,最简单地方法是middle=(left+right)/2middle =原创 2020-08-22 18:42:08 · 1164 阅读 · 0 评论 -
题型总结——前K系列(堆、优先队列)
这里写目录标题1适用场景2堆属性3堆实现5力扣题型总结4堆常用的方法1适用场景求解最大/最小/最频繁的K个元素的题,都遵循这种模式。求解k类型的最佳数据结构就是堆,堆分为最大堆和最小堆,而堆是通过优先队列来实现的,能够动态维护数据的有序性。如下找到数组中前3个最大的值流程:根据题目要求,将K个元素插入到最小堆或是最大堆。遍历剩下的还没访问的元素,如果当前出来到的这个元素比堆顶元素大,那咱们把堆顶元素先删除,再加当前元素进去。2堆属性堆的逻辑结构是一棵完全二叉树的数组对象。堆的物理结原创 2020-08-22 17:30:34 · 446 阅读 · 0 评论 -
算法复杂度分析——时间复杂度(上)
目录1为什么要计算时间复杂度2时间复杂度概念2.1时间频度T(n)2.2时间复杂度3时间复杂度分析3.1示例一3.2示例二4汉若塔问题的时间复杂度4.1题目描述4.2代码实现4.3时间复杂度分析1为什么要计算时间复杂度一个算法的评价主要从时间复杂度和空间复杂度来考虑。2时间复杂度概念2.1时间频度T(n)一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。并且一个算法花费原创 2020-08-15 10:35:00 · 436 阅读 · 0 评论 -
递归学习之Java实现
目录1 斐波那契数列2 `n`的阶乘3汉若塔问题3.1问题描述3.2代码思路3.3代码实现3.3代码流程分析递归调用是指一种通过重复将问题分解为同类的子问题而解决问题的方法。其实就是不断调用自身。1 斐波那契数列斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……斐波那契数列以如下被以递推的方法定原创 2020-08-06 14:38:16 · 396 阅读 · 0 评论 -
二叉树初始化以及对称二叉树判断
1.二叉树结构体struct TreeNode{ int val; TreeNode *left; TreeNode *right; TreeNode(int x) : val(x), left(NULL), right(NULL) {}};2.二叉树初始化TreeNode* initBTree(vector<int> elements){ int eleSize; eleSize = elements.size(); if (eleSize < 1) {原创 2020-07-04 15:14:58 · 149 阅读 · 0 评论 -
二叉树、前序遍历、中序遍历和后序遍历
二叉树和二叉搜索树1定义1.1树的定义及特点定义:树是由结点或顶点和边组成的(可能是非线性的)且不存在着任何环的一种数据结构。没有结点的树称为空(null或empty)树。一棵非空的树包括一个根结点, 还(很可能)有多个附加结点,所有结点构成一个多级分层结构。特点:树状图是一种数据结构, 它是由n (n>=0)个有限结点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像y棵倒...原创 2020-04-07 10:34:38 · 144 阅读 · 0 评论