数据结构和算法动态可视化 :https://visualgo.net/zh
有问题1062290728@qq.com
不知道怎么配图和排版.jpg
放个图镇场子,侵删
归并排序
概述:
归并排序基于
归并
这一简单的基本操作。归并,就是将两个有序的数组合成一个更大的有序数组。以此为基础的进行递归,便产生的递归算法
。
性质:
归并排序最吸引人的性质是它能够保证将任意长度为N的数组排序所需时间和NlogN成正比;
他的主要去点则是它所需的额外空间和N成正比。(额外空间这点主要是因为两个有序数组的归并操作需要和两个数组一起大小的空间进行排序,后面讲到应该懂。)
归并
该方法先将所有元素复制到aux[]中,归并后复制回a[]中。
四个判断条件:
1.左半边用尽(取右半边的元素)
2.右半边用尽(取左半边的元素)
3.右半边当前元素小于左半边当前元素(取右半边的元素)
4.左半边当前元素小于右半边当前元素(取左半边的元素)
- 自顶向下的归并排序:递归。 应用高校算法设计中
分治思想
的最经典的例子。
比较次数的分析:
n=lgN,2n=N。这棵树正好有n层。对于0~n-1之间的任意k,自顶向下的dik层右2k,即第k层被分为2k个数组。每个数组长度为2n-k(单个数组长度=总元素数/数组数),则形成第k层一个数组最多需要2n-k次比较。因此形成第k层需要的比较数为2k2n-k=2n (数组数每个数组最多比较数),则n层总共为n2n=NlgN。
- 自底向上的归并排序:先归并的那些微型数组,然后再成对归并得到的子数组,如此这般,直到我们将整个数组归并在一起。
这种方法比标准递归方法所需要的代码量更少。p175
这种方法比较适合用链表组织的数据。
命题: 对于长度为N的任意数组,自顶向下的归并排序最多需要访问数组6NlgN次。
每次归并最多需要访问数组6N次(2N次复制,2N次用来将排好序的元素移动回去,林外最多比较2N次)。证明没细看,有人要解释再看好了。
命题: 没有任何基于比较的算法能够保证使用少于~NlgN次比较将长度为N的数组排序。
注1:
实现归并的一种直接的方法是在两个有序数组排序时才创建数组分配空间。但是!当用归并将一个大叔组排序时,我们用此方法会进行多次归并,这会带来效率的问题。所以建议直接创建好一个和要排序数组一样大的数组,用完后删除。
注2:
使用插入排序处理小规模的子数组(比如长度小于15)一半可以将归并排序的运行时间所夺10%~15%。
注3:
我们可以节省将数组元素复制到用于归并的辅助数组所用的时间(但空间不行)。要做到这一点要调用两种排序方法,一种将数据从输入数组排序到辅助数组,另一种将数据从辅助数组排序到输入数组。
注4:
spent 2h+局限性:归并排序的空间复杂度不是最用的; 处理比较,算法的其他操作(例如访问数组)也可能很重要; 不进行比较也能将某些数据排序(红黑树?)