zoukankan      html  css  js  c++  java
  • 排序:快速排序

    时间复杂度 最理想 O(nlogn) 最差时间O(n^2)

    像合并排序一样,快速排序也是基于分治模式的。下面是对一个典型子数组A[p..r]排序的分治过程的三个步骤:

    分解:

    数组A[p..r]]被划分成两个(可能空)子数组A[p..q-1]和A[q+1..r],使得A[p..q-1]中的每个元素都小于等于A(q),而且,小于等于A[q+1..r]中的元素。下标q也在这个划分过程中进行计算。

    解决:

    通过递归调用快速排序,对子数组A[p..q-1]和A[q+1..r]排序。

    合并:

    因为两个子数组是就地排序的,将它们的合并不需要操作:整个数组A[p..r]已排序

    快速排序:

    QUICKSORT(A,p,r)
    if p<r
       then q=PARTITION(A,p,r)
            QUICKSORT(A,p,q-1)
            QUICKSORT(A,q+1,r)
    
    

    数组划分:

    PARTITION(A,p,r)
    x=A[r]
    i=p-1
    for j=p to r-1
        do if A[j]<=x
              then i=i+1
                   exchange A[i]<->A[j]
    exchange A[i+1]<->A[r]
    return i+1
    具体可以看下这两图

    可参照c代码:

    int a[101],n;//定义全局变量,这两个变量需要在子函数中使用 
    
    int partion(int left,int right)
    {
        int i,j,t,temp; 
        if(left>right) 
           return; 
                                    
        temp=a[left]; //temp中存的就是基准数 
        i=left; 
        j=right; 
        while(i!=j) 
        { 
                       //顺序很重要,要先从右边开始找 
                       while(a[j]>=temp && i<j) 
                                j--; 
                       //再找右边的 
                       while(a[i]<=temp && i<j) 
                                i++; 
                       //交换两个数在数组中的位置 
                       if(i<j) 
                       { 
                                t=a[i]; 
                                a[i]=a[j]; 
                                a[j]=t; 
                       } 
        } 
        //最终将基准数归位 
        a[left]=a[i]; 
        a[i]=temp; 
        return i;
    }
    
    void quicksort(int left,int right) 
    { 
        int i=partion(left,right);
        quicksort(left,i-1);//继续处理左边的,这里是一个递归的过程 
        quicksort(i+1,right);//继续处理右边的 ,这里是一个递归的过程 
    }

    选取枢纽元问题

    1、糟糕的方法 

         通常的做法是选择数组中第一个元素作为枢纽元,如果输入是随机的,那么这是可以接受的。但是,如果输入序列是预排序的或者是反序的,那么依据这样的枢纽元进行划分则会出现相当糟糕的情况,因为可能所有的元素不是被划入S1,就是都被划入S2中。 

    2、较好的方法 

        一个比较好的做法是随机选取枢纽元,一般来说,这种策略是比较妥当的。 

    3、三数取取中值方法 

        例如,输入序列为  8, 1, 4, 9, 6, 3, 5, 2, 7, 0 ,它的左边元素为8,右边元素为0,中间位置|_left+right)/2_|上的元素为6,于是枢纽元为6.显然,使用三数中值分割法消除了预排序输入的坏情形,并且减少了快速排序大约5%(此为前人实验所得数据,无法具体证明)的运行时间。

    参考:

    旧博客原文

    看算法:快速排序

  • 相关阅读:
    使用 RetroShare 分享资源
    C# 代码占用的空间
    C# 代码占用的空间
    PHP date_timezone_set() 函数
    PHP date_timezone_get() 函数
    PHP date_timestamp_set() 函数
    PHP date_timestamp_get() 函数
    PHP date_time_set() 函数
    MHA软件下载地址
    [ZJOI2019]线段树
  • 原文地址:https://www.cnblogs.com/losophy/p/9521401.html
Copyright © 2011-2022 走看看