更快排序.ppt
文本预览下载声明
更快的排序
When sorting needs to be faster
引言
在前一章当中,我们已经学习了三种排序方法的工作原理
插入排序
选择排序
冒泡排序
尽管它们在不同的条件下会有不同的表现,但是总的来说,三种算法需要的时间相差无几
2
概要
这一章我们将介绍三种更快的排序方法
快速排序
归并排序
排序网络
前两种方法拥有更高的执行效率,在运行速度上优势惊人
最后一种方法涉及到计算机中很重要的一个概念——并行化
3
快速排序
对于处理大量待排序对象的工作来说,快速排序(Quicksort)无疑是最佳选择
快速排序算法是由Tony Hoare设计的
对一百万个对象进行排序,使用快速排序法比冒泡排序法要快将近20000倍
我们将继续上一章中用到的重物和天平的例子来描述其工作原理
4
快速排序
第一步,任选一个重物,将其放置在天平的一端
第二步,将剩下的所有重物依次和这个重物进行对比,将较轻的放在你的左边,较重的放在右边
在所有重物分成两组后,将之前选取的重物放在两组之间
5
快速排序
第一阶段的一种可能的比较结果如下图第一行所示,两组对象中分别包括重量小于50的一组和重量大于50的一组
6
快速排序
一开始被选出的重物我们称它为“基准”(pivot)
基准(上图第一行中的50)在最后排好序的序列中已经处于了正确的位置——它的左侧有4个比它小的重物,右侧有3个比它大的重物
我们不需要再对基准做任何操作,只要把基准两侧的对象再进行排序即可
7
快速排序
在对基准两侧的对象再进行排序时,我们采用的仍然是之前的方式
选择其中的一组,然后重复上述“分裂”的过程,即在该组中随机选出基准对象再将组中剩余的对象“分裂”成两组,比基准对象轻的放左边,比基准对象重的放右边,基准对象放中间
对另一组也进行同样的处理
8
快速排序
如下图所示的第二行,即是第二轮排序后的情况,其中左边一组的基准为20,右边一组的基准为60
9
快速排序
接下来只剩下两组只含两个对象的序列需要再次排序了,而其他的对象则已经处于排好序的状态
对剩下的各组进行同样的操作,直到每组中只有一个对象
当所有组都拆分成单项时,重物序列也完成了从最轻到最重的排序
10
实践与思考
假设有8个重物,使用快速排序法对其进行排序,记录一共比较了多少次
你觉得最多需要多少次比较?
最多的比较次数发生在怎样的情形下?
你觉得最少需要多少次比较?
最少的比较次数发生在怎样的情形下?
针对这样的情形,你觉得快速排序性能的关键在于什么?
11
快速排序
在快速排序中,我们用到了递归(recursion)的原理,即不断用相同的原则将序列划分成越来越小的部分,并采用相同的步骤对各部分排序
实际上,这种特殊的递归法被称为分治(divide and conquer),序列被不断分割知道它足够小到能够直接导出结果
未来的章节我们会进一步学习分治的思想
12
快速排序的伪代码
procedure Quicksort(List)
if (List少于一个元素) then
(退出并报告排序完毕)
选择基准pivot
分割 (Split) List 使得
List[first]…List[splitPoint-1] = pivot
List[splitPoint] = pivot
List[splitPoint+1]…List[last] = pivot
递归调用 Quicksort ( List[first]…List[splitPoint-1] )
递归调用 Quicksort ( List[splitPoint+1]…List[last] )
13
快速排序的伪代码
procedure Split(List)
pivot ← List[first]
left ← first + 1
right ← last
while (left = right) do
while (List[left]pivot且left = right) do (右移left)
while (List[right]pivot且left = right) do (左移right)
if (leftright) then
(交换List[left]与List[right])
splitPoint ← right
交换List[first]与List[right]
14
快速排序的例子
15
快速排序的例子
16
归并排序
归并排序(Merge sort)是建立在归并操作上的排序算法,它同样体现了“分治”的思想
17
归并排序
首先,将待排序序列随机分成两组且对象数量相同(如果总数为奇数,则应让两组数量尽量接近)
然后,分别对两组对象进行排序,再将两组对象归并起来
归并两个已排好序的序列很容易,你只要不断地移出两组对
显示全部