您的位置:首页 > 其它

4 -- 交换排序之快速排序

2015-05-28 14:48 218 查看
四、快速排序算法

         快速排序是冒泡排序的一种改进,冒泡排序排完一趟最大值冒出来了,那么可不可以先选定一个值,然后扫描待排序序列,把小于该值得记录和大于该值得记录分成两个单独的序列,然后分别对这两个序列进行上述操作。我们把选定的值作为枢纽值,如果枢纽值为序列中的最大值,那么一趟快速排序就变成了一趟冒泡排序。 

          快速排序时间与划分是否对称有关。快速排序的平均时间复杂度为o(n*logn),至于为什么是o(n*logn),请参考《算法导论》第7章,书中用递归树的方法阐述了快速排序平均时间。且常数因子很小,所以就平均时间而言,快速排序是很好的内部排序方法。最佳情况下(每次划分都对称)时间复杂度o(n*logn)。最坏情况下(每次划分都不对称,如输入的序列有序或者逆序时)时间复杂度为o(n^2),所以在待排序序列有序或逆序时不宜选用快速排序。此外,快速排序是不稳定的。

           最佳情况下,每次划分都是对称的,由于枢纽值不再考虑,所以得到的两个子问题的大小不可能大于n/2,同时一趟快速排序时间为o(n),所以运行时间递归表达式:

T(n)<=2T(n/2)+o(n)。这个递归式的解法请参考下一篇博客中归并排序效率分析。其解为T(n)=o(n*logn)。
        最坏情况下,每次划分都很不对称,T(n)=T(n-1)+o(n),可以用递归树来解,第i层的代价为n-i+1.总共有n层。把每一层代价加起来有n-1个n相加。所以这个递归式的解为T(n)=o(n^2),此时就是冒泡排序。

   
//递归排序,双向扫描

    public void quickSort1(int a[], int low, int high){

        //low作为枢纽值,把小于该值和大于该值分成两个记录

        if(low>a.length||high>a.length||low<0||high<0)return;

        if(low>=high)return ;

        int pivotkey = a[low];

        int i=low, j=high;

        

        //双向扫描

        while(i<j){

            //i位置是pivotkey,先找到大于pivotkey的放在pivotkey得位置,不会覆盖其他值,

            //然后找到一个大于pivotkey的值a[i]放在j的位置。然后pivotkey放在i的位置

            while(i<j&&a[j]>=pivotkey){

                j--;

            }

            a[i]=a[j];

            while(i<j&&a[i]<=pivotkey){

                i++;

            }

            a[j]=a[i];

        }

        

        a[i]=pivotkey;

        //递归出小于该值得记录

        quickSort1(a, low, i-1);

        

        //递归出大于该值得记录

        quickSort1(a, i+1, high);

    }

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: