交換排序

交換排序是指在排序過程當中,經過待排序記錄序列中元素間關鍵字的比較,將數據元素進行交換來達到排序目的的方法,主要包括冒泡排序和快速排序。git

源碼:https://github.com/fangyz/myDataStructuregithub

/*
冒泡排序的基本思想是對全部相鄰記錄的關鍵字進行比較,若是a[j]>a[j+1]則將其交換,最終達到有序化。其處理步驟以下:
(1)首先將整個待排序的記錄分爲有序區和無序區,初始狀態有序區爲空無序區則爲整個待排序的記錄。
(2)對無序區從前日後依次將相鄰記錄的關鍵字進行比較,若逆序則進行交換,從而使得較大的數據元素右移,這樣最終造成有序序列。
經過上面的步驟能夠發現,每一次冒泡排序都將無序區中最大的數據元素移到有序區的最右邊。而且,對於含n個數據元素的數據序列,最多須要通過n-1趟冒泡排序。
*/
void BubbleSort(int* a,int length)
{
    if (a == NULL || length <= 0)
        return;
    int i, j,temp;
    for (i = length - 1; i > 0; i--){
        for (j = 0; j <i; j++){
            if (a[j]>a[j + 1]){
                temp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = temp;
            }
        }
    }
}

//若是一次循環中,沒有進行數據交換,那麼就說明序列已經有序。
void BetterBubbleSort(int* a, int length){
    if (a == NULL || length <= 0)
        return;
    int i, j, temp;
    bool isChanged=false;
    for (i = length - 1; i > 0; i--){
        isChanged = false;
        for (j = 0; j <i; j++){
            if (a[j]>a[j + 1]){
                temp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = temp;
                isChanged = true;
            }
        }
        if (isChanged == false)
            break;
    }
}
//更好的冒泡排序
void BestBubbleSort(int *a, int length)
{
    int i, j;
    int temp;
    bool isChange;
    int lastMove;
    if (a == NULL || length <= 0)
        return;
    for (i = length - 1; i>0; i--)
    {
        isChange = false;
        for (j = 0; j<i; j++)            //一次執行將最大的數交換到最後面
        {
            if (a[j + 1]<a[j])
            {
                temp = a[j + 1];
                a[j + 1] = a[j];
                a[j] = temp;
                isChange = true;       //優化點1:若是一次循環中沒有數進行交換那說明已經有序了
                lastMove = j;           //優化點2:裏面的for執行完畢後, 說明j到i之間的數據已經有序了,j之前的數據可能還不是有序的。
            }
        }
        if (isChange == false)
            break;
        i = lastMove + 1;
  } }

 冒泡排序是一種穩定的排序方法,由於只有在大於後一個數的狀況下才進行交換。冒泡排序最好狀況比較次數爲n-1,移動次數僅爲0,此時數據元素自己就是有序序列。最壞狀況下比較次數爲n*(n-1)/2,移動次數爲3n(n-1)/2,平均時間複雜度爲O(n^2)。接下來是快速排序。數組

/*
快速排序,能夠看到它的時間複雜度主要集中在外面的while循環,這個循環的做用是進行比較找到一個位置s將數組分爲0~s和s~length,也就是說快速排序的時間複雜度集中在劃分區域上。
在劃分區域時,首先就算劃分了區域,但仍是要對這一整個數組進行比較,比較的次數是一個n階函數,接下來重點就是劃分的次數了。
最好狀況下若是每次都是劃分的中間的區域,那麼劃分次數爲lbn,最壞狀況下若是每次劃分有一個區域是空的,那將會劃分n-1次,故時間複雜度最壞O(n^2),最好是O(lbn)。
至於爲何平均時間複雜度爲O(nlbn)課本上寫了一大堆計算公式然而暫時並無看懂。。。。
*/
void QuickSort(int *a, int start, int end)
{
    if (a == NULL || start < 0 || (start>=end))
        return;
    int s = start, e = end - 1;
    int index;
    int value = a[s];
    while (s < e){
        //必定要注意這個地方加=,由於若是不加的話,就是死循環了。
        //這個地方還有一點要注意,那就是要加上s<e,由於條件是大於或等於,那麼這時有可能e會小於s。
        while (a[e]>=value&&s<e)
            e--;
        //如今執行到這個地方說明a[e]<value了,因此要讓a[s]=a[e],a[e]=value,可是這裏只對a[s]進行了賦值,
        //緣由是在循環中,讓a[s]=a[e]後,接下來的while循環可以繼續執行,當遇到a[s]>value時,此時進行替換的是a[e],即將大的數放到e這個地方。
        //這樣能夠發現讓a[s]=a[e]後就可讓s向前增長,當s增長到a[s]>value時便讓a[e]=a[s],這樣下一次while循環中a[e]便大於value了額,e就能夠向後減小了。
        a[s] =a[e];
        while (a[s] <= value&&s<e)
            s++;
        a[e] = a[s];
        //咱們還能夠發現每次執行到這個地方的時候,數組中有2個重複值,
        //那就是a[e]==a[s]>value,若是不知足s<e跳出循環那就要讓a[s]=value。
    }
    a[s] = value;
    if (s < end - 1)
        QuickSort(a, s + 1, end);
    if (s>start + 1)
        QuickSort(a, start, s);
}
相關文章
相關標籤/搜索