1. 程式人生 > >交換排序之快速排序

交換排序之快速排序

   快速排序是基於交換思想對氣泡排序的一種改進的交換排序方法,又稱分割槽交換排序,它採用分治的策略。

分治思想:將原問題劃分為若干個與原問題結構相似的子問題,遞迴的解決這些子問題,然後將子問題的解組合為原問題的解.
快速排序:在待排序列中,任取一個記錄(通常是第一個記錄),並以該關鍵字作為基準,經過一趟交換之後,所有的比他小的記錄都交換到他的左邊,而所有比它大的記錄都交換到它的右邊,此時,該記錄在序列中的位置就以確定。同時我們把這個問題劃分成了兩部分,然後在分別對這兩個部分重複上述過程,直到每一個部分最終劃為一個記錄為止。
快速排序演算法:QuickSort(RecordType R[],int s, int e)

**{
    int i;
    if(s<e)
    {
        i = Partition(R,s,e);
        QuickSort(R,s,i-1);
        QuickSort(R,i+1,e);
    }
}**

快速排序的核心是劃分子問題:

int Partition(RecordType R[], int s , int e)
{
    int temp;
    temp = R[s];
    while(i<j)
    {
        while(i<j && R[j]>=temp)
            j--;
        if(i < j)
        {
            R[i] = R[j];
            i++;
        }
while(i<j && R[i]<=temp) i++; if(i < j) { R[j] = R[i]; j--; } } R[i] = temp; return i; }

Partition函式完成在給定區間 R[i]~R[j] 中一趟快速排序的劃分。設定兩個搜尋指標 i 和 j 來指向給定區間的頭一個記錄和最後一個記錄,並將頭一個記錄作為基準記錄。首先從 j 指標開始從右向左搜尋關鍵字比基準記錄關鍵字小的記錄,找到後將其交換到 i 指標處;然後 i 指標右移一個位置並由次開始自左向右搜尋關鍵字比基準記錄關鍵字大的記錄,找到後將其交換到 j 指標處;接著 j 指標左移一個位置並繼續上述自右向左搜尋、交換的過程。如此兩端交替向中間搜尋、交換,直到 i 與 j 相等,i 左側的記錄都比基準記錄小,而 j 右側的記錄及其關鍵字都比基準記錄的關鍵字大,而 i 和 j 所指向的這同一個位置就是基準記錄最終要放的位置。

下圖是一趟快速排序的示意圖:
一趟快速排序示意圖

從空間效率看:快排是遞迴的,每層遞迴呼叫的指標和引數都要用棧來存放。儲存開銷在最理想的情況下為O(log2n ),最壞情況下,遞迴呼叫是一個單支樹,空間複雜度為O(n).
從時間效率上看:對n個記錄的待排序列,一次劃分需要約n次關鍵字的比較,時間效率為O(n)。若設T(n)為對n個記錄進行快速排序所需的時間,則理想情況下每次劃分正好將n個記錄分為等長的子序列,並且每次劃分所需要的比較次數為n-1;則T(n)<= n+2T(n/2) = n+2(n/2+2T(n/4))=2n+4T(n/4) = O(nlog2n)
在最壞的情況下,每次劃分只得到一個子序列,即時間複雜度為O(n2)

#include <stdio.h>

void QuickSort(int array[],int left,int right);
int Partition(int array[],int left,int right);
int main()
{
    int array[10] = {23,12,321,10,2,1,89,20,13,25};
    int i;
    QuickSort(array,0,9);
    for(i=0;i<10;i++)
    {
        printf("%d ",array[i]);
    }
    return 0;
}

int Partition(int array[],int left,int right)
{
    int temp;
    temp = array[left];
    while(left<right)
    {
        while(left<right && array[right]>=temp)
            right--;
        if(left < right)
        {
            array[left] = array[right];
            left++;
        }
        while(left<right && array[left]<=temp)
            left++;
        if(left < right)
        {
            array[right] = array[left];
            right--;
        }
    }
    array[left] = temp;
    return left;
}

void QuickSort(int array[],int left,int right)
{
    int mid;
    if(left<right)
    {
        mid = Partition(array,left,right);
        QuickSort(array,left,mid-1);
        QuickSort(array,mid+1,right);
    }
}