排序算法概要

选择排序

每次选择一个最小(最大)的元素,放到数组的最前面。
过程:在要排序的一组数中,首先遍历一遍,找到最小的数,和放在第一个位置的数交换。然后从第二个数开始遍历,找到最小的数,和放在第二个位置的数交换。就这样一直循环,直到最后只剩下一个数。
由以上过程可以知道,选择排序算法总是按照固定的流程来运行,不会因为输入数字的特点的不同,而导致算法的执行步骤不同,因此选择排序算法有一个重要特点:运行时间和输入数据的特点无关
对于有n个元素的数组,选择排序算法需要比较 n(n1)2 次,需要交换 n1 次,每次交换只需要一个单位的额外空间,因此该算法为原地工作。时间复杂度为 O(n2)
排序算法不是稳定的,例如要排序[5 9 5 2],前面的元素5就会被交换到最后一个位置。


插入排序

每次获取一个元素,把它插入到已排序的子数组中的适当位置。

直接插入排序

首先可以认为第一个元素是一个有序的子数组,然后选中第二个元素,把它插入到之前的子数组(该数组中只有一个元素)中,使其有序。这样前二个元素组成的子数组是有序的,以此类推,选择第三个,第四个元素。。。最后一个元素,插入到合适的位置,就可以使整个数组有序。
为确定插入位置,可以对已排序的数组逐个元素进行比较来确定位置,然后插入选中的元素。使用这种方法:
- 最好情况下需要比较 n1 次,元素交换 0 次(此情况下数组正好是有序的)。
- 最差情况下需要比较 n(n1)2 次,需要交换 n(n1)2 次元素。(这是对于数组而言。对于链表,每个元素插入到合适的位置只需要移动一次)
因此插入排序算法运行时间和输入有关。数组有序程度越高,运行时间越快。最差时间复杂度 O(n2) ,最优时间复杂度 O(n)
直接插入排序需要一个额外空间用来交换元素,为原地工作的。直接插入排序是稳定的。

二分插入排序

二分插入排序和直接插入排序的不同就是确定插入位置的方法不同,直接插入排序是将待插入元素和数组进行逐个比较,而二分插入排序利用了要插入的数组是有序的这一特点,使用二分查找来确定插入位置。
因此二分查找的比较次数为 nlogn 次。


希尔排序

将各个h子数组(数组中间隔为h的元素组成的数组)进行插入排序。缩小h的值,不断迭代这一过程,直到h为1。
开始的时候h比较大,元素为跳跃式的移动(因此希尔排序是不稳定的)。后来随着h的缩小,数组有序程度越来越高,最后使用插入排序(此时h=1)。而插入排序中每次元素只移动一个位置。
希尔排序是对插入排序的改良,先通过某些方法让数组基本有序,然后进行输入排序,减少了插入排序移动和比较元素的次数。因此希尔排序也叫做分组插入排序
分组长度h一般选取 hn=3hn1+1 ,即[1,4,13,40…]这样的数列
需要1个额外空间用来交换元素,空间复杂度为 O(1) 。时间复杂度大约为 O(n1.5) 。使用不同的h序列,时间复杂度就不同。


归并排序

将两个有序的子数组归并(合并)起来,形成一个更大的有序数组

自顶向下归并

将数组的左右半边分别进行排序,然后把他们归并(合并)起来。而数组左右半边的排序又要用到归并排序。 这是一个递归的算法。

归并算法的空间复杂度为 O(n) ,用来保存归并后的数组。
最好情况下比较大约 12nlogn 次,移动 nlogn 次;最差情况下比较 nlogn 次,移动 nlogn 次。因此时间复杂度为 O(nlogn)
算法的优化:
1. 由于每次递归需要保存现场,恢复现场等。所以当子数组元素较少的时候,改用其他非递归的算法(比如插入排序等)比较省时间。
2. 当子数组有序的时候,就不必再对其进行排序。因此可以先判断一下是否有序,然后在进行排序。
3. 每一趟归并,需要把子数组的元素先复制到一个临时数组,把临时数组归并到原数组中。假设这两个数组为a和b,我们可以先把a中的元素归并到b中,在下一趟的时候把b中的元素归并到a中,交替着来。这样就不用每次都要先复制一遍数组了,减少了代码运行时间。

自底向上归并

自底向上的归并算法和普通的自顶向下的归并不同

最后说一句,归并排序是稳定的。


快速排序

  1. 将小于某个元素的所有元素放在其左边,其他的放在右边,然后对左右两个子数组进行此过程,直到左右两个数组均有序。
  2. 和归并算法是互补的:归并是先递归再归并,快排是先元素分类再递归。
  3. 运行时间和输入有关?无关?
  4. 需要1个额外空间?
  5. 3-way partition sort(当重复元素比较多的时候)
  6. 当子数组长度较短的时候,可以改用其他非递归算法
  7. 每趟访问n次,交换n/2次。最好logn趟,最坏n趟。

堆排序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值