
数据结构与算法
文章平均质量分 79
程序猿小乙
一个技术码农,分享自己这些年的一些职场收获,技术内容。
展开
-
计数排序的简单理解
计数排序作为一种线性时间复杂度的排序算法,其要求输入的数据必须是。,核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。计数排序的时间复杂度可以达到 O(n+k),其中 k 是。只有这两个条件都满足,才能最大程度发挥计数排序的优势。数组元素的取值越集中,算法耗费的时间越短。原创 2023-04-17 08:55:44 · 151 阅读 · 0 评论 -
归并排序的简单理解
归并排序的基本思想是,将已有序的子序列合并,可以得到有序的完整序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为。每次合并操作的平均时间复杂度为 O(n),而完全二叉树的深度为 log2n,总的平均时间复杂度为 O(nlogn)。归并排序速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的序列。归并排序的比较次数小于快速排序的比较次数,移动次数一般多于快速排序的移动次数。并且,归并排序的最好、最坏、平均时间复杂度均为 O(nlogn)。原创 2023-04-12 08:38:57 · 172 阅读 · 0 评论 -
快速排序的简单理解
快速排序通过一趟排序将待排序列分割成独立的两部分,其中一部分序列的关键字均比另一部分序列的关键字小,则可分别对这两部分序列继续进行排序,以达到整个序列有序的目的。快速排序通过一趟排序将待排序列分割成独立的两部分,其中一部分序列的关键字均比另一部分序列的关键字小,则可分别对这两部分序列继续进行排序,以达到整个序列有序的目的。当该序列趋于有序时,能够让效率提高,但在整个序列数全部相等的时候,随机快排的效率依然很低。当该序列趋于有序时,能够让效率提高,但在整个序列数全部相等的时候,随机快排的效率依然很低。原创 2023-04-11 08:27:12 · 374 阅读 · 0 评论 -
希尔排序的简单理解
希尔排序又称为缩小增量排序,主要是对序列按下标的一定增量进行分组,对每组使用直接插入排序算法排序;由于希尔排序花费的时间还由增量间隔决定,平均时间复杂度并不能明确得出,平均时间复杂度可看作为 O(n1.3∼2)。插入排序是稳定的排序算法,但是,由于希尔排序使用了增量间隔进行插入排序,希尔排序并不能像插入排序保持稳定,排序过程中会出现相等的两数前后顺序不一致。希尔排序是插入排序的一个优化版本,利用优化的策略使用插入排序,提高效率,没有使用到额外的内存空间,因此希尔排序是原地排序算法。原创 2023-04-10 09:15:59 · 428 阅读 · 0 评论 -
插入排序的简单理解
在其实现过程中使用双层循环,外层循环针对除了第一个元素之外的所有元素,内层循环针对当前元素前面的有序表进行待插入位置查找,并进行移动。对于值相同的元素,可以选择将后面出现的元素,插入到前面出现元素的后面,这样就可以保持原有的前后顺序不变,所以插入排序是稳定的排序算法。插入排序的基本思想是:将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增 1 的有序表。插入排序算法的运行并不需要额外的存储空间,所以空间复杂度是 O(1),也就是说,这是一个原地排序算法。最坏情况时间复杂度为 O(n2);原创 2023-04-09 07:45:23 · 386 阅读 · 0 评论 -
选择排序的简单理解
选择排序的工作原理是:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾,以此类推,直到全部待排序的数据元素的个数为零。与冒泡排序两两比较交换不同,选择排序算法是最小的元素与固定位置的元素进行交换,当这个固定位置的元素被交换到另一个位置之后,也就有可能导致相等的数字次序变化。无论原序列是有序还是无序,选择排序都需要对序列做完整的遍历,即最好情况时间复杂度和最坏情况时间复杂度都是 O(n2);平均时间复杂度是 O(n2)。原创 2023-04-08 11:44:07 · 469 阅读 · 0 评论 -
冒泡排序的简单理解
冒泡排序是一种交换排序,基本思想是在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。为了保证冒泡排序算法的稳定性,当有相邻的两个元素大小相等时可以不做交换,相同大小的数据在排序前后不会改变顺序,所以冒泡排序是稳定的排序算法。使用最优时间复杂度解法,原序列是有序时的时间复杂度是 O(n);平均时间复杂度是 O(n2)。冒泡排序是一个原地排序算法,过程只涉及相邻数据的交换操作,只需要常量级的临时空间,它的空间复杂度是 O(1)。原创 2023-04-07 08:35:18 · 1050 阅读 · 1 评论 -
如何分析排序算法
这样选择的原因是,时间复杂度为 O(n2) 的排序算法会比 O(nlogn) 的排序算法的效率低,一般指的都是时间复杂度在没有系数、常数、低阶介入比较的情况,当真正使用的时候,这些是不可避免的。而对于超过 286 个元素的序列,还会判断这个序列是否结构化(数据是否时升时降),结构化的序列会使用归并排序算法,而非结构化的序列仍然会使用快速排序算法。比如说,计数排序算法适用于较集中的小范围整数序列,桶排序算法适用于容易划分为桶的均匀整数序列,计数排序适用于可划分为具有递进关系的“位”的整数序列。原创 2023-04-06 09:45:33 · 325 阅读 · 0 评论 -
算法的复杂度分析
复杂度分析法是对已知的代码进行效率分析的方法,与之相对的是使用实际数据运行代码的事后统计法。测试结果非常依赖测试环境。硬件的不同会对测试结果有比较大的影响,比如不同处理器的执行时间会不一样测试结果受数据的影响很大。对同一个排序算法,待排序数据的有序度会影响算法的执行时间;对于小规模的数据排序,插入排序的效率会比快速排序的效率更高相比事后统计法,复杂度分析法更能表示一个算法在各个维度的综合性能。原创 2023-04-05 10:19:21 · 664 阅读 · 0 评论 -
一致性哈希的简单认识
在分布式集群中,对机器的添加、删除或者是机器故障后自动脱离集群等操作是分布式集群管理最基本的功能。如果采用的是常见的取模哈希算法,当有机器添加、删除之后,需要对数据做迁移,非常麻烦。而一致性哈希利用哈希环的概念,保证增加或减少服务器,数据存储的改变最少,相比取模哈希算法大大节省了数据移动的开销,非常方便。平衡性:指哈希的结果能够尽可能分布到所有的缓存中,这样可以使得所有的缓存空间都能得到利用单调性。原创 2023-04-04 08:49:01 · 857 阅读 · 0 评论 -
B+ 树的简单认识
在 B+ 树中,关键字只存储在叶子结点,非叶子结点存储的是叶子结点所存储关键字的部分拷贝,所有的叶子结点也都在相同的高度,叶子结点本身按关键字大小从小到大链接。当数据量非常大时,索引占用的空间也会非常大,索引还是得存储在磁盘上,如果树的层级较大,则进行磁盘 IO 的次数就会越多,性能就会越差。但是对应 B+ 树而言,B 树的层级仍然会比 B+ 树的高,且范围查询没有 B+ 树方便,这是舍弃 B 树而选择 B+ 树的主要原因。B+ 树是 B 树的一种变体,从某个程度上看,B+ 树可以认定是 B 树的升级版。原创 2023-04-03 09:16:53 · 511 阅读 · 0 评论 -
B 树的简单认识
B* 树是 B+ 树的变体,在 B+ 树的基础上,非叶子结点(除根结点外)会增加指向同一层兄弟的指针,且非叶子结点关键字个数至少为 2m3,即块的最低使用率为 23(B+ 树为 12)。对于 B+ 树,关键字只存储在叶子结点,非叶子结点存储的是叶子结点所存储关键字的部分拷贝,所有的叶子结点也都在相同的高度,叶子结点本身按关键字大小从小到大链接。使用 B 树作为索引结构时,由于结点的大小等于一个页的大小,通常阶会比较大,因此树的深度较浅(通常不超过 3),查找效率非常高。原创 2023-04-02 11:32:19 · 727 阅读 · 0 评论 -
AVL 树的简单认识
自平衡是指在对平衡二叉树执行插入或删除结点操作后,可能会导致树中某个结点的平衡因子绝对值超过 1,即平衡二叉树变得“不平衡”,为了恢复该结点左右子树的平衡,此时需要对结点执行旋转操作。为了保证二叉树的平衡,AVL 树引入了监督机制,就是在树的某一部分的不平衡度超过一个阈值后触发相应的平衡操作,保证树的平衡度在可以接受的范围内。RL 型和上面的 LR 型对称,A 结点的平衡因子为 2,右孩子 C 结点的平衡因子为 -1。也可以使用平衡因子来定义:A 结点的平衡因子为 2,右孩子 C 结点的平衡因子为 1。原创 2023-04-01 11:51:35 · 324 阅读 · 0 评论 -
跳表的简单认识
假设每两个结点会抽出一个结点作为上一级索引的结点,那第一级的索引个数大约就是 n2,第二级的索引个数大约就是 n4,以此类推,第 k 个索引的结点个数是第 k-1 个索引的结点个数的 12,那么,第 k 个索引的结点个数就是 n2k。同样的,假设每两个结点会抽出一个结点作为上一级索引的结点,那第一级的索引个数大约就是 n2,第二级的索引个数大约就是 n4,依次类推,最终索引占用的空间将是 n2+n4+...+4+2=n−2。实际上,跳表是一种使用空间换时间的数据结构,以增加索引的方式,提高检索数据的效率。原创 2023-03-31 10:09:13 · 359 阅读 · 0 评论 -
哈希表的简单认识
快速计算和均匀分布。哈希算法的方向是单向的,从哈希值不能反向推导出原始数据哈希算法的转换是敏感的,原始数据任何一点变动,得到的哈希值都会大不相同哈希冲突的概率要极小的,不同的原始数据,经过哈希算法得到的哈希值相同的概率很小哈希算法的执行效率是高效的,即使是很长的文本也能快速计算出哈希值。原创 2023-03-30 09:43:38 · 466 阅读 · 0 评论 -
堆的简单认识
从上图可以看到,数组中下标为 i 的结点的左子结点,就是下标为 2i 的结点,右子结点就是下标为 2i + 1 的结点,其父结点就是下标为 i/2 的结点。从下往上堆化的过程比较简单,实际上就是将插入的元素与父结点进行比较,出现不符合特性的情况就互换两个结点,一直重复这个过程,直至父子结点之间满足堆的特性。通常,对于大根堆会比较较大的子结点,对于小根堆会比较较小的子结点,出现不符合特性的情况就互换两个结点,一直重复这个过程,直至父子结点之间满足堆的特性。这种方法堆化之后的结果,肯定满足完全二叉树的特性。原创 2023-03-29 08:50:08 · 356 阅读 · 0 评论 -
二叉树的简单认识
树是一种抽象数据类型,用来模拟具有树状结构性质的数据集合。树的结点:包含一个数据元素及若干指向子树分支的信息结点的度:一个结点含有的子树数目称为该结点的度树的度:树中最大的结点度称为树的度叶子结点:也称终端结点,结点度为零的结点分支结点:也称非终端结点,结点度不为零的结点子结点:一个结点含有的子树的根结点称为该结点的子结点父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点兄弟结点:具有相同父结点的结点互称为兄弟结点堂兄弟结点:父结点在同一层的结点互为堂兄弟结点。原创 2023-03-28 09:19:12 · 96 阅读 · 0 评论 -
栈的简单认识
基于数组实现的栈存在一个限制,即数组在声明之后是固定大小的,当栈满的时候,则无法再次往数组中添加数据。将数组的尾部作为栈顶,入栈和出栈都只在栈顶做相应处理,使用一个变量表示数组存储的元素个数,这样入栈、出栈的操作都能达到 O(1) 的时间复杂度。实际上,支持动态扩容的顺序栈在实际开发中并不常见。每进入一个函数,就会将临时变量作为一个栈帧入栈,当被调用函数执行完成,返回到上层函数之后,再将这个函数对应的栈帧出栈。在物理存储层面,栈既可以用数组实现,也可以用链表实现,在这两种数据结构的基础上增加栈的限制即可。原创 2023-03-26 13:11:54 · 125 阅读 · 0 评论 -
链表的简单认识
假设,要在链表中插入一个结点,在知道插入位置的前后两个相邻结点的前提下,只需将新结点的后继指针指向下一个结点,然后将上一个结点的后继指针指向这个新结点,即可完成插入结点的操作。这里的存取指的是通过下标的方式去访问数据,链表无法像数组一样使用寻址公式,只能通过头结点作为入口,根据指针一个结点一个结点地依次遍历,直到找到对应的结点。在实际编码中,为了方便,会使用哨兵结点占据头结点的位置,其信息域是空的,指针域存储实际的头结点所在位置,尾结点的指针域一般会是。双端链表是在单向链表的基础上,增加了尾结点的引用。原创 2023-03-25 12:08:00 · 150 阅读 · 0 评论 -
数组的简单认识
数组本质上是一种 线性表 数据结构,它用一组 连续的内存空间,来存储一组具有 相同类型的数据。如上图所示,线性表就是数据排成一条线一样的结构,在线性表中,每个数据都只有前后两个方向。与线性表相对的是非线性表结构,在非线性表中,每个数据会存在多个方向,数据之间不仅仅只是简单的前后关系,而是呈现发散型的关系。在数组中,存储数据的内存空间是连续的。也就是说,当一段内存空间标明用于存储数组元素,则这一片空间只会存储数组元素,不会再拆分出来存储其他的数据。在数组的原始定义中,数组只能存储相同类型的数据,这样可以保证数原创 2023-03-24 17:57:16 · 268 阅读 · 0 评论