七大排序(簡潔明瞭,註釋分明,思路清晰)

七大排序

不廢話,直接上代碼,註釋分明,思路清晰。

sortingmethod.h

#ifndef SORTINGMETHOD_H
#define SORTINGMETHOD_H

#include <iostream>

#define SORTTYPE int

using namespace std;

/**
 * insert sort
 */
/*direct insert sort*/
void direct_insert_sort( SORTTYPE *arr,int len);

/*shell sort*/
void shell_sort(SORTTYPE *arr,int len);


/**
 * select sort
 */
/*simple select sort*/
void simple_select_sort( SORTTYPE *arr ,int len);

/*heap sort*/
void heap_sort(SORTTYPE *arr,int len);
void adjust_max_heap(SORTTYPE *arr, int len,int i);
void build_max_heap(SORTTYPE *arr , int len);


/**
 * exchange sort
 */
/*bubble sort*/
void bubble_sort( SORTTYPE *arr ,int len);

/*fast sort*/
void quick_sort(SORTTYPE *arr , int start, int end);





/**
 * merge sort
 */
void merge_merge_sort(SORTTYPE *arr , int first, int mid ,int last , SORTTYPE *temp);
void devide_merge_sort(SORTTYPE *arr , int first, int last , SORTTYPE *temp);
void merge_sort(SORTTYPE *arr, int len);


/*show element*/
void show_element(SORTTYPE *arr , int len);

#endif // SORTINGMETHOD_H

sortingmethod.cpp


#include "sortingmethod.h"


/*
 * All sorting is from min to max
 */

/**
 * insert sort
 */
/*direct insert sort*/
void direct_insert_sort( SORTTYPE *arr,int len){

    int temp ,i=0,j=0;              /*temp暫存arr[i]*/

    for(i = 1 ; i < len ; i++){
        /*對每一個arr[i]~arr[0]的數*/
        temp = arr[i];
        for(j=i ; j>0 ; j -- ) {

            /*當arr[j-1]比tem大時,向右移動一個位置*/
            if ( arr[j-1] > temp ){
                arr[j] = arr[j-1];
            }
            else
                break;
        }

        /*此時j剛好爲重複的那個數字*/
        arr[j] = temp;
    }

//    for(i = 1; i<len ; i++){
//        temp = arr[i];
//        for(j = i-1 ; j > -1 ; j--){
//            if(arr[j]>temp){
//                arr[j+1] = arr [j];
//            }
//            else
//                break;
//        }
//        arr[j+1] = temp;
//    }

}

/*shell sort*/
void shell_sort(SORTTYPE *arr,int len){
    /*
     * 將待排序數組按照步長gap進行分組,然後將每組的元素利用直接插入排序的方法進行排序;
     * 每次將gap折半減小,循環上述操作;
     * 當gap=1時,利用直接插入,完成排序。
     */
    int i=0,j=0,k=-1,temp=-1;
    int gap = len / 2;      /*初始化gap,一般時len的一半*/

    while( gap >= 1  ){

        for( i = gap ; i < len ; i+=gap ){
            k = i; temp = arr[k];
            for( j = i - gap ; (j >= 0)&&(arr[j] >temp); j -=gap ){
                arr[j+gap] = arr[j];
                k = j;
            }
            arr[k] = temp;
        }
        gap /=2;
    }

}

/**
 * select sort
 */
/*simple select sort*/
void simple_select_sort( SORTTYPE *arr ,int len){
    /*
      簡單選擇排序的基本思想:比較+交換。
        從待排序序列中,找到關鍵字最小的元素;
        如果最小元素不是待排序序列的第一個元素,將其和第一個元素互換;
        從餘下的 len - 1 個元素中,找出關鍵字最小的元素,重複(1)、(2)步,直到排序結束。
        因此簡單選擇排序也是通過兩層循環實現。
            第一層循環:依次遍歷序列中的每一個元素
            第二層循環:將遍歷得到的當前元素依次與餘下的元素進行比較,符合最小元素的條件,則交換。
    */
    int i=0,j=0,k=0,min,tem;
    for(i=0; i < len ; i++ ){
        min = arr[i];
        /*下面這個循環找到本輪的最小值和下標*/
        for(j = i+1 ; j < len ; j++){
            if(arr[j] < min){
                min = arr[j];
                k = j;
            }
        }

        /*如果arr[i]>min則需要交換*/
        if(arr[i] > min){
           tem= arr[i];
           arr[i] = arr[k];
           arr[k] = tem;
        }

    }



}

/*heap sort*/
   /*
    堆排序按照以下步驟完成:

    1.首先將序列構建稱爲大頂堆;
    (這樣滿足了大頂堆那條性質:位於根節點的元素一定是當前序列的最大值

    2.取出當前大頂堆的根節點,將其與序列末尾元素進行交換;
    (此時:序列末尾的元素爲已排序的最大值;由於交換了元素,當前位於根節點的堆並不一定滿足大頂堆的性質)

    3.對交換後的n-1個序列元素進行調整,使其滿足大頂堆的性質;

    4.重複2.3步驟,直至堆中只有1個元素爲止
    */


/* 調整大頂堆 */
void adjust_max_heap(SORTTYPE *arr, int len,int i){
    /*
     * arr:待調整序列
     * len: 序列長度
     * i:需要調整的結點
     */

    /*定義一個int值保存當前序列最大值的下標*/
    int largest = i; int left,right;

    /*執行循環操作任務:1.尋找最大值的下標;2.最大值與父節點交換*/
    while (1) {
        /*獲得序列左右葉子節點的下標*/
        left = i*2+1; right = i*2+2;

        /*當左葉子節點的下標小於序列長度 並且 左葉子節點的值大於父節點時,將左葉子節點的下標賦值給largest*/
        if(left < len  && arr[left] > arr[largest]){
            largest = left;
        }else{
            largest = i;
        }

        /*當右葉子節點的下標小於序列長度 並且 右葉子節點的值大於父節點時,將右葉子節點的下標值賦值給largest*/
        if(right < len && arr[right] > arr[largest])
            largest = right;

        /*如果largest不等於i 說明當前的父節點不是最大值,需要交換值*/
        int temp;
        if(largest != i){
            temp = arr[i];
            arr[i] = arr[largest];
            arr[largest] = temp;
            i = largest;
            continue;
        }else{
            break;
        }
    }
}
/*建立大頂堆*/
void build_max_heap(SORTTYPE *arr , int len){
    for( int i = (len-1)/2; i>-1; i-- ){
        adjust_max_heap(arr,len,i);
    }
}

/* 堆排序  heap_sort */
void heap_sort(SORTTYPE *arr,int len){
    /*先建立大頂堆,保證最大值位於根節點;並且父節點的值大於葉子結點*/
    build_max_heap(arr , len);

    /* i = 當前堆中序列的長度.初始化爲序列的長度*/
    int i = len;

    /*執行循環:1. 每次取出堆頂元素置於序列的最後(len-1,len-2,len-3...)
              2. 調整堆,使其繼續滿足大頂堆的性質,注意實時修改堆中序列的長度*/
    int temp;
    while( i > 0){
        temp = arr[i-1];
        arr[i - 1] = arr[0];
        arr[0] = temp;
        /*堆中序列長度減1*/
        i-=1;
        /*調整大頂堆*/
        adjust_max_heap(arr , i , 0);
    }
}



/**
 * exchange sort
 */
/*bubble sort*/
void bubble_sort( SORTTYPE *arr ,int len){
    int temp;

    for(int i =0 ; i < len ; i++ ){
        for(int j = len-1; j>i ; j --){
            if (arr[j] < arr[j-1]){
                temp = arr[j]; arr[j] = arr[j-1]; arr[j-1] = temp;
            }
        }
    }

}

/*quick sort*/
void quick_sort(SORTTYPE *arr ,int start,int end){
    /*快速排序的基本思想:挖坑填數+分治法
        從序列當中選擇一個基準數(pivot ,這裏選擇序列當中第一個數最爲基準數)
        將序列當中的所有數依次遍歷,比基準數大的位於其右側,比基準數小的位於其左側
        重複步驟1.2,直到所有子集當中只有一個元素爲止。
        用僞代碼描述如下:
        1.i =left; j = right; 將基準數挖出形成第一個坑a[i]。
        2.j--由後向前找比它小的數,找到後挖出此數填前一個坑a[i]中。
        3.i++由前向後找比它大的數,找到後也挖出此數填到前一個坑a[j]中。
        4.再重複執行2,3二步,直到i==j,將基準數填入a[i]中
     */


    int i, j ,pivot;
    if (start <end){
        i = start;
        j = end;
        pivot = arr[start];
    }
    else
        return;             /*注意這個地方容易忘*/

    while(i < j){

        /*從右開始向左尋找第一個小於pivot的值*/
        while(i < j && arr[j] >= pivot)
            j-=1;

        /*將小於pivot的值移到左邊*/
        if(i < j){
            arr[i] = arr[j];
            i+=1;
        }

        /*從左開始向右尋找第一個大於pivot的值*/
        while (i < j && arr[i] <= pivot)
            i+=1;

        /*將大於pivot的值移到右邊*/
        if(i<j){
            arr[j] = arr[i];
            j-=1;
        }
    }

    /*循環結束後,說明 i=j,此時左邊的值全都小於pivot,右邊的值全都大於pivot*/
    arr[i]=pivot;

    show_element(arr,14);
    /*pivot的位置移動正確,那麼此時只需對左右兩側的序列調用此函數進一步排序即可*/
    /*遞歸調用函數:依次對左側序列:從0 ~ i-1//右側序列:從i+1 ~ end*/
    quick_sort(arr,start,i-1);

    cout<<"left is all right"<<endl;
    quick_sort(arr,i+1,end);
}


/**
 * merge sort
 */
/*
 *  merge_sort
 * 歸併排序的函數
 */
void merge_sort(SORTTYPE *arr,int len){
    /*
    歸併排序是建立在歸併操作上的一種有效的排序算法,該算法是採用分治法的一個典型的應用。
    它的基本操作是:
        將已有的子序列合併,達到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。

    歸併排序要做兩件事:
        分解----將序列每次折半拆分
        合併----將劃分後的序列段兩兩排序合併
    因此,歸併排序實際上就是兩個操作,拆分+合併

    如何合併?
    arr[first...mid]爲第一段,arr[mid+1...last]爲第二段,並且兩端已經有序,現在要將兩端合成達到arr[first...last]並且也有序。

    (1)依次從第一段與第二段中取出元素比較,將較小的元素賦值給temp[]
    (2)重複執行上一步,當某一段賦值結束,則將另一段剩下的元素賦值給temp[]
    (3)此時將temp[]中的元素複製給arr[],則得到的arr[first...last]有序

    如何分解?
    (1)採用遞歸的方法,首先將待排序列分成A,B兩組;
    (2)重複對A、B序列分組;
    (3)直到分組後組內只有一個元素,此時認爲組內所有元素有序,分組結束。
    */

    SORTTYPE  temp[len];
    /*調用歸併排序*/
    devide_merge_sort(arr, 0 , len-1 , temp);

}
void merge_merge_sort(SORTTYPE *arr , int first, int mid , int last , int *temp){

    /*合併的函數----將序列arr[first...mid]與序列arr[mid+1...last]進行合併*/
    int i = first, j = mid +1 ,k = 0;

    /*當左右兩邊都有數時進行比較,取較小的數*/
    while(i <= mid && j <= last){
        if( arr[i] <= arr[j])
            temp[k++] = arr[i++];
        else
            temp[k++] = arr[j++];
    }

    /*如果左邊序列還有數*/
    while(i <= mid)
        temp[k++] = arr[i++];

    /*如果右邊序列還有數*/
    while(j <= last)
        temp[k++] = arr[j++];

    /*將temp當中該段有序元素賦值給L待排序列使之部分有序*/
    for(int x = 0; x < k ; x++)
        arr[first + x] = temp[x];

}
/*這是分組的函數*/
void devide_merge_sort(SORTTYPE *arr , int first, int last , SORTTYPE *temp){
    int mid;
    if(first < last){
        mid = (first + last)/2;

        /*使左邊序列有序*/
        devide_merge_sort(arr, first ,mid ,temp);

        /*使右邊序列有序*/
        devide_merge_sort(arr, mid+1 , last ,temp);

        /*將兩個有序序列合併*/
        merge_merge_sort(arr, first ,mid , last,temp);
        show_element(arr , 14);
    }
}



/*show element*/
void show_element(SORTTYPE *arr , int len){
    for(int i = 0; i < len ; i++ ){
        SORTTYPE tem = arr[i];
        cout<<tem<<"   ";
    }
    cout<<'\n';
}

main.cpp

#include <iostream>

#include "sortingmethod.h"

using namespace std;

int main()
{
    SORTTYPE arr[] = {8,1,13,7,3,12,4,6,2,14,5,9,11,10};
    int len = 14;
    show_element(arr, len);

//    direct_insert_sort(arr,len);

//    bubble_sort(arr , len);

//    shell_sort(arr,len);

//    simple_select_sort(arr,len);

//    heap_sort(arr , len);

//    quick_sort(arr,0,13);

//    merge_sort(arr,len);

   cout<<"sort ending!"<<endl;
    show_element(arr, len);

    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章