arraylist从大到小排序_论数组的N种排序算法

本篇文章仅介绍顺序表(即数组)的N种常见的排序算法,以后遇到有意思的算法还会持续补充。其他数据结构的排序不在本文讨论范围内。本文所有算法由C#代码实现,将32位有符号整数int类型(取值范围[-2^31,2^31-1])数组按从小到大排序。

排序算法分类大致如下(不全,有时间就慢慢补充吧)

cb11f9e36b42aef8dd6555c23657f42d.png
2019年7月6日更新

内部排序:排序期间所有元素均在内存里。

外部排序:排序期间元素无法全部存放在内存中,必须在排序的过程中根据要求不断地在内存,外存中移动。


在正式讨论排序算法前,我们先思考三个问题:

问题一:如何交换两个数的值?

方法一:通过临时变量。另外通过Stack和Queue就不说了。

ec1b73d8f33734dfed5a066ff7476dc7.png

方法二:通过算数运算。相比方法一,不用开辟临时变量的内存,但是多了几步算数运算的过程。通过算数运算分两种:一种是加减,一种是乘除。其中加减运算通用性较高,其次是乘除运算,因为乘除无法对0进行操作,且比加减运算更容易超出数据类型的最大值限制。下面以加减运算为例,展示代码及过程。如果要换为乘除运算,将“+”替换为“*”,“-”替换为“/”即可。

23760730033e316583874bd83faefafe.png

cc97934c2337acdb14d0392d125c1f9f.png
加减运算交换图示

方法三:通过异或运算。先回顾下C#里的四个逻辑运算符。

  • &:位与,都1才1
  • |:位或,有1就1
  • ^:位异或,不一样为1
  • ~:位非,取反

以上是四个逻辑运算符的二进制解释,最简单的方式是下面韦恩图的解释。

  • &:与,取两者的交集
  • |:或,取两者的并集
  • ^:异或,取两者都没有的部分
  • ~:非,取反

9017100dc340061164249285deb6dd1d.png
韦恩图异或交换图示

95907d36d4d9708777d16a2e3d648e6c.png

问题二:如何随机打乱一个数组?

这个问题还是很有意义的,比如在游戏里玩家抽奖前,正面随机顺序展示若干张抽奖卡。

fbe9dfa3ce02e4af4f173036de53d3b2.png

问题三:什么是排序的稳定性?

稳定与不稳定的区别就是相同值的元素排序后是否保留排序前的先后顺序,保留则为稳定。假如只有两个糖果分别分给考试成绩前两名的同学,他们的区别就是下面这样。。。

54b7d5f68522647edf31a2bf0b59da7b.png

本文还会用到如下两个方法:

19ba650c9f54684e8beb0239df3ce951.png

f5618b0a5c032389d77135fc9837b662.png

第一种排序:冒泡排序

初学编程的人可能接触到的第一个排序算法就是冒泡排序。所谓的“泡”指的是每一次外层循环所移动到数组后面的一个最大的值。冒泡排序对数组的重新排列是从末尾开始,即按从后往前的方向,将数组元素从大到小排列。下面展示了一种未优化的冒泡排序算法。

020b9af47de86b6c3e13781314af90b4.png

上面的排序还有许多可优化的点,下面结合动图展示一种优化后的冒泡排序算法。这里只展示相对通用的优化方式,如果有相对具体的排序数据模型,就可以深度定制优化方案。本文其他排序算法均展示相对通用、易于理解的写法。

bcfd1e0af996131f7ae2bad37d254687.gif
每次外循环得到的橙色数字,就是“泡”

17a0edf6d418e0aa958f69af48490bab.png

冒泡排序的时间复杂度比较移动(即交换)的次数决定,下面展示优化的效果

67d274525db118899f8654b05b6283f9.png

7f30d444f4c66e747d3bdd20a42cf937.png

第二种排序:直接插入排序

直接插入排序的核心就是维护一个开头开始的按从小到大排好的局部数组(局部数组初始元素为0号索引),每往后遍历一个新元素,就考虑将之插入到局部数组中,循环往复,使之充满整个数组。

5cdfa51f58b3c91c137e2089c8ccd426.gif

67c058ba0f89c4236d6dcad7d95db0a2.png

第三种排序:简单选择排序

简单选择排序的核心也是维护一个开头开始的按从小到大排好的局部数组(不过这个局部数组没有初始元素),每次遍历后半部分数组,找出最小的红色数加到局部数组的最后面。从图中两个5可以看出,简单选择排序是不稳定排序。

d4d29f996e251b45f6ae6fdcd3f20bfe.gif

b2671280901c78aff7cb681ec4e190b6.png

第四种排序:快速排序

施工中。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值