【编程珠玑】第十一章 排序 (插入排序和快速排序的深度优化)

一,概述

        1)插入排序

         要找到合适的位置,需要判断前一个元素比t小而后一个元素比t大。然后将t插入正确位置。

         比较a[j-1]  跟 a[j] 的关系很关键


         isort1: 没有到达最终位置,就交换该元素和它前面的元素

#include <algorithm>

    isort2:将库函数替换
 


isort3:减少移动次数



 2)快速排序
    qsort1:O(nlog(n)时间和O(logn)的栈空间
 


qsort2:双向划分避免所有元素都相等时候的最坏情况



思路:n个相同元素组成的数组,插入排序性能最好(每个元素需要移动的距离都为0),时间复杂度为o(n)。 快速排序的性能则很糟糕,n-1次划分每次划分都需要0(n)的时间来去掉一个元素,所以时间复杂度为O(n*n) 采取的对策是:采取两个内循环,第一个向右移过小元素,遇到大元素停止,第二个左移,遇到小元素停止。然后交换。 当遇到相同的元素时,停止扫描,交换a[i] 和 a[j]的值。最坏时间复杂度O(nlogn)


   qsort3:利用随机位置的数做轴,会使数组的快速排序得到优化。
 

 
【知识点】产生某个范围随机数方法:
 
    比如要产生 [60-99]的随机数.
    使用rand()函数产生的随机数是从0(包括0)开始的
    我们思考: 

    [ 0, ?] + 60 = [60,99]
    很明显,?应该是39.产生[0, 39]的随机数可以这样做:rand() % 40  得解.




rand()%(end-start)+start;


注意:因为rand()函数是按指定的顺序来产生整数,因此每次执行上面的语句都打印相同的值,所以说C语言的随机并不是真正意义上的随机,有时候也叫伪随机数


 
二,习题
     2)Lomuto的快速排序算法如下
       
      采用哨兵优化后算法:(减少了内循环测试)

      
        5)没完全理解题意
        
        6)选择排序
          希尔排序:选择排序的优化

 
        9)线性时间寻找第k小元素
          思路:快速排序选择一个pivot对数组进行划分,左边小于pivot,右边大于等于pivot,所以我们计算左边小于pivot(加上pivot)的个数count总共有多少,如果等于k,正是我们所要的,如果大于k,说明第k小的数在左边,那就在左边进行我们的递归;否则,在右边,那么说明右边的第k-count小的数就是我们所要的,在右边进行我们的递归。
          算法实现一:

 

算法实现二:


      14)算法实现如下:









 

posted @ 2012-05-18 11:07  Java EE  阅读(275)  评论(0编辑  收藏  举报