排序算法

排序算法

七个基于比较的排序算法
1.插入排序 | 希尔排序
2.选择排序 | 堆排序
3.冒泡排序
4.快速排序
5.归并排序


插入排序

  • 插入排序
    时间复杂度:平均O(n2),最好O(n),最差O(n2)。
    算法原理:把数组同样分为有序区和无序区,每次从无序中拿一个数,在有序区中找到它的何时位置,加入到有序区。与选择排序不同的是,选择是把最值加入,位置在加入前已经确定,插入是随机拿一个数加入,加入后才找它的位置。

  • 步骤(升序):

    1. 从第一个元素开始,单独看可以认为已经排序完成
    2. 取出下一个元素A,在有序区从后向前遍历
    3. 如果A元素比这个位置的元素B小,就把元素B后移,直到B比A还要小就出循环
    4. 在循环完后把A元素插入到B元素的后一位

希尔排序

  • 思路:利用插入排序数组越接近有序,效率越好,在插入排序之间进行预排序。
  • 如何分组:动态分组,开始分多组,越来越少。
  • 分组大小:1.gap = size/3 + 1 2.gap = size / 2;
  • 空间复杂度:O(1)
  • 稳定性:不稳定,相同的两个数可能分道不同的组里。

选择排序

  • 时间复杂度:都是O(n^2)。
    最稳定的排序,因为无论初始顺序是什么样子,时间复杂都是O(n^2),所以慎用,好处是不占用额外空间。

  • 算法原理:首先在未排序的数组中找到一个最大(小)值,然后把这个值放入有序区,一直重复n-1次,
    减治算法排序:每次从无序区间选择一个数,插入到有序区间的合适位置。

  • 步骤(升序):

    1. 最开始整个数组都是无序数组, 无序区:[0,n] ,有序区为空。
    2. 遍历数组,从当前数组中遍历找到最大值,放入当前数组的最后。

优化:双重选择排序,定义两个下标(min,max),每次循环都找出最大值和最小值,把最小值放在当前循环的最左边,最大值放在当前循环的最右边。注意:有可能最左边原本的值为最大值,交换之后需要更新下标max(max =min,因为把左值和min交换了)

冒泡排序

  • 时间复杂度:平均O(n2),最好O(n),最差O(n2)。 稳定性:稳定
  • 算法原理:一种比较常见的排序,通过重复的走过需要排序的元素,每次比较两个元素的大小,如果顺序不对就把顺序交换,一直交换到不需要在交换为止。以递增为例,则每次都会把最大的数交换到最后一位。
  • 步骤(递增):
    1. 从第一位元素开始,比较相邻两个元素的大小,把大的向后交换。
    2. 对后续的每一个元素进行相同的事情,直到最大值被交换到最后一位。
    3. 再次开始下一轮交换,除了最后一位元素。
    4. 循环1-3步骤。

优化:因为是两两相比,最后一位数再n-1次就已经被比较过了,所以外层循环也可以减1.

快速排序

  • 时间复杂度:最好(有序):O(nlog(n)) 平均:O(nlog(n)) 最坏(逆序):O(n^2)

  • 算法原理:找一个基准值把数组分为两半,左边小于基准值,右边大于基准值,一直递归直到有序。

  • 步骤:(最好前闭后闭)

    1. 拷贝数组,保证原数组不变

    2. 做排序,三步

       1. 终止条件(数组长度大于1就继续)
       2. 找基准值				
       3. 给基准值左右继续排序。
      
    • 如何找基准值
    1. 前后下标找大小值再交换。

      可以直接把基准值定为下标。

    2. 挖坑法

      必须把基准值定为数值,因为在埋坑的时候会把下标坑里的值变化,下标里的值不一定为当初的,最后一次交换也交换的是基准值。

    3. 整体循环法。

      定义一个下标index记录大于基准值的第一个值,整体循环i,小于基准值的时候进入判断,交换index和i,让index往后走一位。

归并排序

  • 时间复杂度:最好(有序):O(nlog(n)) 平均:O(nlog(n)) 最坏(逆序):O(n*log(n))

  • 空间复杂度:O(n)

  • 算法原理:采用分而治之的思想,把数组一直对半分,直到每个数组长度都为1之后再按照顺序合并。

  • 步骤(递归,最好前闭后开):

    1. 判断出递归条件(array.length<2)
    2. 计算中间下标,把数组一分为二,左右两个子数组继续归并排序
    3. 合并数组(注意:合并的是两个子数组,之后要按照合并的更新原数组的值)
  • 步骤(非递归)

    1. 两层循环,外层代表分裂的最小数组长度,从1开始,每次乘2,内层代表这次两个子数组的合并长度,第一次不合并,之后每次加两个最小数组长度。
    2. 把数组的起始low,中间mid,结尾high表示出来,mid和high需要和数组长度作比较,mid大于数组长度说明不足以进行一次合并,就跳出内部的合并循环,要合并的长度大于数组长度就把high变成数组长度,就是还剩下多少就合并多少。
    3. 合并数组(注意:合并的是两个子数组,之后要按照合并的更新原数组的值)

参考:https://www.runoob.com/w3cnote/ten-sorting-algorithm.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值