快速排序

l  枢纽元(pivot):集合中的任意一个元素

如何取枢纽元:

1.  错误的做法是:将第一个元素作为枢纽元。如果输入是随即的,这样的做法还是可以接受的,可是如果输入是预排序的,这样就产生了一个劣质的分割,有可能所有的元素都被划入了S1,而S2没有元素。

2.  一种安全的做法:随即选取。这种方法非常安全,但是产生随即数开销很大。

3.  中值分割法:例:8,1,4,9,6,3,5,2,7,0。取第一个元素8,最后一个元素0,和[left+right]/2个元素6.于是枢纽元就是6.

 

l  分割策略:

分割是一种很容易出错或者低效的操作,安全的做法:第一部通过将枢纽元与集合最后一个元素交换,使枢纽元离开要分割的集合,i从集合的第一个元素开始,j从元素的倒数第二个开始。

8       1       4       9       0       3       5       2       7       6

↑                              ↑

i                               j

         假设所有的元素互异,在分割阶段要做的是:把所有的小元素移到数组的左边,大元素移到数组的右边,大小是相对于枢纽元的。

         取得枢纽元的代码:(此处取法非常繁琐,可以利用一个小排序,如果要处理的是个元素数量比较小的数组,那么此处显然占据了很多效率,个人认为这也是快速排序不适用小数组的一个原因)

             public int getIndexOfPivot(int[] list, int begin, int end) {

        // 求的是中值index

        int middle = (begin+end)/2;

    if((list[middle]>list[begin]&&list[middle]<=list[end])||(list[middle]<=list[begin]&&list[middle]>list[end])){

            return (begin+end)  /2;

        }else if((list[end]>list[begin]&&list[end]<=list[middle])|| (list[end]>list[middle]&&list[end]<=list[begin])){

            return end;

        }else{

            return begin;

        }

    }

 

         移动过程:当i在j的左边时,讲i右移,当i指向的元素小于枢纽元时,并讲j左移,移过那些比枢纽元大的元素。当i和j停止时,i指向了一个大元素,j指向了一个小元素,如果i在j的左边,那么讲这两个元素互换。当i和j交错时,不在交换,这时将枢纽元与i所在位置的元素交换。最后利用分治法的思想,将枢纽元两侧的子数组进行递归排序,直到数组起始位置大于终止位置时,递归结束。

         快速排序过程的完整代码实现如下:

public classQuickSort {

    // core sort

    public int[] sort(int[] list, int start, int end) {

        if (start < end) {

            int pivotPos = getIndexOfPivot(list,start, end);

            int pivot = list[pivotPos];

            // swap the pivot and the last element

            list= swap(list, pivotPos, end);

            int j = end;

            // begin scan

            if (j < 0) {

                System.out.println("There is not enough element to sort!");

            }

           

            int i = start-1;

            while (true) {

                // find the first position

                while (list[++i] < pivot ){

                    //移过那些小于枢纽元的元素

                }

                while((j-1)>=0&&list[--j] > pivot ) {

                    //移过那些大于枢纽元的元素

                }

                if (i < j) {

                    swap(list,i, j);

                }else{

                    break;

                }

            }

            // when the loop is over,then swap the element[i] and thepivot

            swap(list,i, end);

            sort(list,start, i-1);

            sort(list,i + 1, end);

           

            return list;

        }else{

            return list;

        }

           

    }

 

    public int getIndexOfPivot(int[] list, int begin, int end) {

        // 求的是中值index

        int middle = (begin+end)/2;

    if((list[middle]>list[begin]&&list[middle]<=list[end])||(list[middle]<=list[begin]&&list[middle]>list[end])){

            return (begin+end)  /2;

        }else if((list[end]>list[begin]&&list[end]<=list[middle])|| (list[end]>list[middle]&&list[end]<=list[begin])){

            return end;

        }else{

            return begin;

        }

    }

 

    public int[] swap(int[] a, int pos1, int pos2) {

        int temp = a[pos1];

        a[pos1]= a[pos2];

        a[pos2]= temp;

        return a;

    }

 

    public void print(int[] list) {

        for (int i = 0; i < list.length; i++) {

            System.out.println(list[i]);

        }

    }

 

    public static void main(String[] args) {

         int[] a = { 8, 1, 4, 9, 6, 3, 5, 2, 7, 0 };

        QuickSortqs = newQuickSort();

        a= qs.sort(a, 0, 9);

        qs.print(a);

    }

}

 

l  快速排序的分析:

最差情况:枢纽元始终是最小元素,时间复杂度为O(N2);

最好情况:枢纽元始终在中间,时间复杂度为O(NLogN);

平均情况:O(NLogN).

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值