码迷,mamicode.com
首页 > 编程语言 > 详细

排序的稳定性

时间:2017-12-17 23:56:13      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:列排序   需要   好处   之间   第一个   改变   div   img   例子   

什么是排序稳定性?  

  通俗地讲就是在排序前A的位置是 i ,B的位置是 j,此时 i < j,则如果在排序后A的位置还是在B之前,那么称它是稳定的。

它的好处是,如果排序算法是稳定的,那么第一个排序结果可以为另一个排序所用。比如基数排序,先按低位排序,逐次按高位排序,低位相同的元素其顺序在高位也相同时是不会改变的。

 

首先给出一张在前一个博客“时间复杂度入门理解”中出现过的一副图,给出相关排序的稳定性:

  技术分享图片

接下来,将解释图中某些排序是不稳定的的原因。

 

I)为什么希尔排序不稳定?

A:首先要知道 Shell 排序是基于插入排序的优化排序,插入排序每次本身只能插入一位数据,希尔排序按照步长对多个元素进行插入排序。我们知道一次插入排序是稳定的,但是同时对多组数据进行插入排序,很明显就稳定了,举例:

有这样一组数:[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ]

以第一轮是步长为5的希尔排序为例:

Before Shell Sort:

技术分享图片 

After Shell Sort:

技术分享图片 

很明显,之前 94 相对于 33 的位置就变了,这就是同时进行多次插入排序所导致的不稳定性。

 

II)为什么快速排序不稳定?

A:快排的思想是先设一个中枢元素(也称是基准数,对照用),对两遍进行排列,需要满足左边的元素都比中枢元素小,右边元素都比中枢元素大,随后对左和右的子序列也进行这样的操作(分治)。而该排序不稳定的关键就是中枢元素在调换到序列中间的时候,会破坏了原来位于中央的元素的稳定性,比如有一个序列:

6 1 2 7 9 3 4 5 10 8 ,我们定义 6 为中枢元素

进行第一轮快排后,得3 1 2 5 4 6 9 7 10 8

这样操作就会把 3 的稳定性破坏。所以快排是一个不稳定的排序算法,不稳定发生在中枢元素的交换时刻。

 

III)为什么选择排序是不稳定的?

A:选择排序的操作是这样:先在未排序的序列中选择最小的元素(或最大的元素),把它放入第一个位置,再在剩余未排序序列中选择第二小的,放在第二个位置...以此类推,直到所有序列排序完毕。但是,这样直接让最小元素与第一个位置上的元素进行交换,会破坏第一个元素的稳定性。

举个例子:6 2 1 7 9 3 4 5 10 8

在6 和 1 的交换同时,6 与 2的稳定性就被破坏了。

 

IV)为什么堆排序是不稳定的?

A:堆的结构是第 i 个结点的左子结点为 2i ,右子结点为2i + 1,子结点 i 的父结点的位置在 floor( (i-1)/2 ),最大堆要求父结点要大于它的两个子结点,最小堆要求父结点要小于它的两个子结点。而堆排序就是移除位于第一个数据的根结点,并做做大堆调整的递归运算。

在一个长为n的序列中,首先从第 n/2 个结点和其子结点一共三个结点开始选择是最大堆还是最小堆,这三个元素的选择当然并不会影响稳定性。但是之后第n/2 -1 ,n/2 -2, ... 2, 1 个结点开始选择就会影响稳定性了。因为有可能第 n/2 -2 个父结点把其后的一个元素交换了,而第 n/2 -3 个父结点的后一个结点却没有被交换,那么它们之间的稳定性就被破坏了。

 

注意

  排序算法是否为稳定的是由具体算法决定的,不稳定的算法在某种条件下可以变为稳定的算法,而稳定的算法在某种条件下也可以变为不稳定的算法。比如冒泡,若让交换的条件改成 r[j] >= r[j+1],两个相等的记录就会交换位置,从而变成不稳定的算法。

排序的稳定性

标签:列排序   需要   好处   之间   第一个   改变   div   img   例子   

原文地址:http://www.cnblogs.com/Bw98blogs/p/8053679.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!