常用排序算法原理总结

前面有篇文章总结了性能,同时强调了算法原理才是最重要的,仅仅记住一些性能指标的数据,是没有用的。这篇文章主要以较“精炼简单”但是又“详细啰嗦”的语言来描述算法实现的细节过程!注意:可能不适合初学者看,初学者应该先看算法书籍以及实现的源码,然后再参考下文叙述来帮助理解算法实际的原理!本篇没有实例代码,请参看《大话数据结构》的C源码和个人的github的java源码链接!(《大话数据结构》java语言实现

一、简单排序
1、冒泡:起始时,从最后一个数字开始逐个与前面的数字比较(小则替换,大则不替换),直至确定当前的索引号的位置;(外循环确定当前索引号,内循环执行冒泡比较)
  冒泡plus:添加一个标志位,用来记录上一次外循环比较的时候是否发生交换,如果没发生交换,说明已经排序好了,以后的外循环排序就没有必要了,所以直接跳出就可以了!

2、简单选择:起始时,规定当前外循环的索引号为最小值,然后后续数字都和这个最小值比较,直到比较完后,确定新的最小值,然后才交换(注意比较的时候不交换);继续循环,确定下一个索引号的最小值;(PS:其实就是找最小值然后插入0位,然后再找剩下的最小值(即第二最小)插入1位,依次类推,和冒泡不同的是,冒泡每次从后边往前面比较而且都交换,然后“冒”上来!这个是从前往后比找到最小值最后才交换)

3、直接插入:起始时选择i=2位置的记录值作为比较对象(i=0为哨兵位)并缓存至i=0位,然后开始从i-1位->0位元素逐个与当前数据比较(已经缓存到0位了,其实也就是和0位比较),比它大则说明i-1位不应该在当前i位的左侧,所以后移,直到遇到比它小或者等于(等于的时候比较到0位了)的则退出比较。此时空出的位置就是i=2记录值的新位置,以此类推;
  直接插入plus:从倒数第二个开始比较,即首先取出n-1位,并缓存!从n-2->0位顺序开始比较,比它大则后移,比它小则停止比较,把缓存的当前的数据插入到此时空出的位置,重新缓存当前比它小的数据,以此类推 !(PS:原理都是一样的,但是从后往前比其实逻辑更好理解)

4、希尔排序:参见直接插入,只不过希尔排序不是-1的比较,而是-n的比较(PS:希尔排序也是插入排序,都是先缓存当前位数据!只不过希尔排序每次从-1位开始开始和当前位比较,然后步进为-1向前进军;希尔排序首先就从-n位开始当前位比较,然后步进为-n向前进军。二者都是遇到比它大的数字,然后大数字后移,当然后移的位置也是1位和n位的差别!还有就是n并不是一个定值,比如建议n=n/3+1,n初始值为序列长,经过这个计算后才是第一次用到的步进值!当序列遍历到最后一个节点的时候(初始化从n+1开始遍历),则再次计算n值)

二、高级排序:
5、堆排序:构造堆——首先把序列看成是一个层序遍历的二叉树,然后起始点默认是length/20,开始比较所在的根节点和子节点大小(共三个数字记录),把最大的数字记录交换为当前根节点,然后依次类推变成一个大顶堆(假设length=9,则分别把(4,9)(3,9)(2,9)(1,9)变成大顶堆);排序——把堆低的数字记录(末尾)和root节点交换,然后继续构造剩余数据记录(即(1,8)(1,7)(1,6)…..)的大顶堆,以此类推直到最后排序完成。

6、归并排序:拆分归并——首先会把序列进行递归拆分,直到出现拆分过后当前栈内首位=末尾,则跳出循环继续递归拆分上一个栈的另半边序列,再跳出循环开始归并比较!在跳出循环进入下一轮左拆分、右拆分、归并的步骤,直到最后比较完!排序——归并思想很简单,就是找到一个辅助空间(这里是辅助数组),然后分别比较原来两个序列当前位置的数字大小(默认都是首位),谁小谁就归并到辅助数组内,然后派出下一个数组继续比较(类似车轮战),最后总有一个序列先把数字“派出来”完了,然后没有被派出来完的数组直接把剩余数组追加到辅助数组后面就行了!(注意归并的时候,两个序列已经是分别有序的了)
  归并排序plus(非递归模式):上述递归实现拆分归并比较难理解,而且会占用较大的空间(空间复杂度是nlogn)!,所以建议使用非递归的方式来进行拆分和归并!这个很好理解,首先选取1,2位比较然后归并;3,4位比较,然后归并……..,一轮下来将会出现两两有序(奇数会剩余一个);在进行第二轮的两两归并,将会出现四四有序,最后四四归并,出现八八有序……..直到最后全部有序!(PS:非递归方式空间复杂度只有n,时间性能也有提升,所以性能更优,请优先使用!)

7、快速排序:枢轴值——起始时选择首位数字记录开始比较,然后从两边向中间遍历,比它大的通过交换放在右边,比它小的通过交换放在左边(每次交换后,才把比较的“焦点”从一边转向另一边,即两边向中间遍历。所以并不是第一次比较左边,第二次就比较右边了,而是发生交换后才从左边移向右边),最后首位数字记录值的索引号将发生改变这个索引号就是枢轴值;然后对低字表再次递归求枢轴值,对高字表再次递归求枢轴值(PS:很有前几天二叉树推导算法的递归思想)
  快速排序plus:三数取中——对首位、中间位、高位求枢轴值,最后确定变换后的首位数字记录为整个序列的枢轴值;枢轴值——把当前枢轴值的数字记录备份到i=0位,由原来的交换改为替换,当遍历的时候发现替换的两个数字记录相等,则当前位置就是实际的枢轴值;然后排序

注:以上为排序算法的原理性描述,期间涉及递归、循环等,尤其是索引号的确认(+1或者-1什么的)以及跳出的条件需要实际编程调试。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值