数据结构 排序及其时间复杂度大汇总!!

冒泡排序 O(n^2)

前后两两数据进行比较,交换,大的数值往后走,小的数值往前走,一轮之后最大的数值到达正确位置,再多进行几轮使之都到达正确的位置

时间复杂度 O(n^2)

数据量x

第一轮:比较了x-1次

第二轮:比较了x-2次

第三轮:比较了x-3次

......

第k(x-1)轮:比较了1次

第一轮把最后一个数排好了j=0

第二轮把最后两个数排好了不用再排了j=1

-j是为了让排好的不再排

选择排序 O(n^2)

默认待排序数组第一个为最小值,找待排序数组中真正的最小值,找待排序数组真正的最小值和待排序数组的第一个位置进行交换 ---- 真正的最小值到达正确位置

时间复杂度 O(n^2)

第一轮:x

第二轮:x-1

第三轮:x-2

...

第x(k)轮:1

插入排序 O(n^2)

1、认为数组当中的第一个数值是已经排好序的数值

2、定义一个游标:从第二个数值开始,不断地向后进行遍历

3、游标指向的数据插入已经排好序的数组当中

如何实现插入按顺序排序??

定义 j 游标,j 游标指向 i 的前一个数值,j 和 j+1 指向的数据进行比较

  • 如果 j+1 指向的数据比 j 大,则插入完成
  • 如果 j+1 指向的数据比 j 小,则 j 和 j+1 指向的数据进行交换。j-1,直到 j+1 指向的数据大或者 j=0,j 不再向前移动,插入完成

时间复杂度 O(n^2)

j 和 j+1

第一轮:i = 1 1次操作

第一轮:i = 2 2次操作

第一轮:i = 3 3次操作

...

第x-1轮:i = x-1 x -1次操作

越小的数值在后面,j 和 j+1 移动的次数越多,所以有

希尔排序(缩小增量排序)O(nlogn)

1、将数组按照数据长度的一半为间隔(步长)进行分组(奇数的话向下取整),组内进行插入排序--------小的数值在前面,大的数值在后面

2、将数组按照数据长度的一半的一半为间隔(步长)进行分组(奇数的话向下取整),组内进行插入排序--------小的数值在前面,大的数值在后面

3、将数组按照数据长度的一半的一半的一半为间隔(步长)进行分组(奇数的话向下取整),组内进行插入排序--------小的数值在前面,大的数值在后面

...

直到无法继续分组,步长为1的时候整个数组成为一组,进行插入排序,这时候只需要微调即可

时间复杂度 O(nlogn)

忽略j和j+1的移动,因为小的大部分都在前面,j和j+1交换的次数少了,可以忽略。

看 i 遍历的次数,都看成x次

堆排序 O(nlogn)

① 利用完全二叉树构建大顶堆

② 堆顶的元素和堆底的元素进行交换,除堆底元素之外,其余元素继续构建大顶堆

③ 不断地重复②(构建大底堆),直到数据全部被处理,排序完成

完全二叉树,按照从上到下,从左到右的顺序排列(与平衡二叉树是独立的)

大顶堆:要求父节点的值大于等于其左右孩子的值

构建数组:

知道流程了,所以如何构建大顶堆

从后往前依次对每一个元素进行维护,让这个元素符合大顶堆

有孩子的话一定会有左孩子

1、定义parent游标,指向要维护的节点;定义child游标,指向parent的左孩子

有孩子一定会有左孩子:

2、父子节点进行比较。如果父节点的值大,则符合大顶堆

3、如果子节点的值大,则parent指向的节点不符合大顶堆

4、父子节点进行交换,交换完成之后,parent指向child,child指向左右孩子的更大值,重复2 3 4,直到父节点的值大或者child为空

只需要维护堆顶元素即可

重复步骤二,所以每个尾结点都要换上来,直到结束,一直变的是堆顶元素,所以需要维护每一个堆顶元素,x个数据就是x个

因为只有堆顶元素和堆底元素进行互换了,只有堆顶元素变了 ------ 从堆顶往下遍历

时间复杂度 O(nlogn)

维护一个节点的时间复杂度:和层数相关 O(logn)

  • 维护单个节点,都可以看成从上往下
  • 维护单个节点,不论你是根节点还是其他的都是logn。维护一个是节点都是logn
  • 比较下一层是左右任意挑一个,所以每层只与下节点比较一次

O(logn)

总体的时间复杂度:

的时间复杂度:O(nlogn)

第一大步里,是从后往前,所有的都维护了一遍所以nlogn

对所有的数据都需要维护,一共x个数据

从下往上遍历,每到一个节点就要立马维护

的时间复杂度:O(nlogn)

第二大步里,是每一个节点都跑到了最上边,所以每个也是对n个节点进行维护的,所以也是nlogn

基数排序 O(kn)

基数大,最大数值小

定义0-9 十个桶

排序到多少位由最大的数值决定

取数据,先进来的先取走,依次取出再依次按十位放入

重复...

没有位数的话就是0

时间复杂度 O(kn)

一共x个数

按照个位:2x (放进取出) O(n)

按照十位:2x (放进取出) O(n)

按照百位:2x (放进取出) O(n)

...

按照k位:... (放进取出) O(n)

O(kn) k不能省去,因为不知道k有多大

归并排序 O(logn)

合并有序序列:把两个短小的但是是有序的序列排序

先拆分再合并,在合并的过程中借助临时空间(没有形成新数组)进行合并

拆分??在中间位置拆开,数据分成左右两部分,按此逻辑继续拆分,拆分成一个一个的时候停止

时间复杂度 O(nlogn)

拆分:代码实现的时候,只是left和right换了一个值而已,所以实际没有拆分,不算时间复杂度

合并:每一轮需要遍历n个数据,一共logn轮,O(nlogn)

快速排序 O(nlogn)

1、定义待排序数组当中的第一个作为基准数

2、定义 j 游标,j游标从后往前移动,找比基准数小的值,找到后停下

3、定义 i 游标,j游标从前往后移动,找比基准数小的值,找到后停下

4、i 和 j 数值进行交换

5、重复2 3 4,直到 i 和 j 相遇

6、相遇位置的数据和基准数进行交换,交换完成之后,基准数到达正确位置

7、以基准数为起始点进行拆分,分成左右两部分 重复上述所有,直到数据都被拆分开停止(也没有产生新数组,用的临时空间)

把这些移上去之后,独立的数据就到位了

时间复杂度 O(nlogn)

每一轮都需要遍历n个数据,一共logn轮,O(nlogn)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值