您的位置:首页 > 理论基础 > 数据结构算法

快速排序优化分析

2014-04-21 21:25 232 查看
上一篇的《浅谈快速排序》 http://blog.csdn.net/g96968586/article/details/24185967  

中我们分析了快速排序的算法,我们也举了一个例子来模拟快速排序,然而大家发现了没有,上次是对数组{50,10,90,30,70,40,80,60,20}进行排序,如果这一次我换成下面这个例子会发生什么情况呢?

前一篇的Partition函数代码:
int Partition ( SqList *L,int low,int high)
{
int pivotkey;
pivotkey = L->r[low];   /* 用子表的第一个记录作枢轴记录 */
while(low < high)   /* 从表的两端交替向中间扫描 */
{
while(low < high && L->r[high] >= pivotkey)    high - - ;
swap(L,low,high);    /* 将比枢轴记录小的记录交换到低端 */
while(low < high && L->r[low] <= pivotkey )   low ++;
swap(L,low,high);  /* 将比枢轴记录大的记录交换到高端 */
}
return low;   /*  返回枢轴所在位置 */
}


如果我们对数组{9,1,5,8,3,7,4,6,2}进行排序,由代码第四行“pivotkey = L->r[low]; ”知道,我们应该选取9作为第一个枢轴pivotkey,此时经过一轮“pivot=Partition(L,1,9)”,它只是更换了9和2的位置,并把9返回给pivot。整个数组并没有实质性的变化。如图示,



换句话说,第四行代码“pivotkey = L->r[low]; ”变成了一个潜在的瓶颈。排序速度的快慢取决于L->r[l1]的关键字处在整个序列的位置,L->r[1]太大或太小都回影响性能。在我们现实中,带排序的序列极有可能是基本有序的,如果我们总是固定地选择第一个关键字作为首个枢轴,就变成了极为不合理的做法。

这里的改进方法我们采用三数取中法。即取三个关键字先进行排序,将中间数作为枢轴,一般是取整个待排序的左端、右端和中间三个数,也可以随机选取。这样至少这个中间数一定不会是最小或者是最大的数,从概率来说,取三个数均为最小或最大的可能性微乎其微,因此中间数位于较为中间的值的可能性就大大提高了。
我们现在在Partition函数的第三行和第四行中间加入这么一段代码,



这样子,如果我们对数组{9,1,5,8,3,7,4,6,2},取左9、中间3、右2来比较,最终使得L->r[low] = 3,一定要比9和2来的更合理。

下面来优化一些不必要的交换。

大家发现了没,上一篇中,对于50这个关键字,其位置变化是1->9->3->6->5,可其实它的最终目标就是5,当中的一些交换是不需要的。因此,我们再次对Partition函数进行优化。



优化之后少了多次交换数据的操作,在性能上又得到了部分的提高。

看程序分析,





今天就到这吧o(∩_∩)o,顺便吐槽一下,CSDN怎么认为我的代码有敏感词汇,总是不让我保存和发布,最后我只能在自己电脑上敲入代码,截图发布上来了,如果谁在我的代码上看到了敏感词汇,请告诉我,谢谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息