小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

算法基礎(chǔ):常用的排序算法知識筆記

 IT技術(shù)分享社區(qū) 2022-10-20 發(fā)布于江蘇

1、算法外排序分類

              

2、冒泡排序

冒泡排序(Bubble Sort)屬于交換排序,它的原理是:循環(huán)兩兩比較相鄰的記錄,如果反序則交換,直到?jīng)]有反序的記錄為止。

實現(xiàn)算法:

/**

 * 冒泡排序優(yōu)化后的算法

 * 設(shè)置一個標(biāo)記來標(biāo)志一趟比較是否發(fā)生交換

 * 如果沒有發(fā)生交換,則數(shù)組已經(jīng)有序

 */

void bubbleSort(SqList *L){

    int i,j;    

    int flag = true;  // flag 用來作為標(biāo)記

    for (i = 1; i < L->length && flag; i++) { 

  // 若flag為true 則說明數(shù)據(jù)交換過,否則沒交換過(數(shù)組已經(jīng)有序) 則停止循環(huán)

        flag = false;

        for (j = L->length - 1; j >= i; j--) {

            if (L->r[j] > L->r[j+1]) {

                swap(L, j, j+1);

                flag = true;  // 如果有數(shù)據(jù)交換 flag為true

            }

        }

    }

}

3、簡單選擇排序

簡單選擇排序法(Simple Selection Sort)是通過n-i次關(guān)鍵字間的比較,從n-i+1個記錄中選出關(guān)鍵字最小的記錄,并和第i(1<=i<=n)個記錄交換。

原理是:每一次從無序數(shù)據(jù)組的數(shù)據(jù)元素中選出最小(或最大)的一個元素,存放在無序數(shù)組的開始位置,隨著無序數(shù)組元素減少,有序組元素增加,直到全部待排序的數(shù)據(jù)元素完全排完。

/**

 * 簡單選擇排序算法

 */

void selectSort(SqList *L){

    int i, j, min;

    for (i = 1; i < L->length; i++) {

        min = i;    // 將當(dāng)前下標(biāo)定義為最小值下標(biāo)

        for (j = i + 1; j <= L->length; j++) {

            if (L->r[min] > L->r[j])

                min = j;

        }

        if (i != min)  // 若min不等于 i 說明找到最小值, 交換

            swap(L, i, min);

    }

}

4、直接插入排序

直接插入排序(Straight Insertion Sort)的是將一個記錄插入到已經(jīng)排好序的有序表中,從而得到一個新的、記錄增1的有序表。

原理:將一個記錄插入到一個已經(jīng)排序好的表中,得到一個記錄增加1的有序表。并且它把當(dāng)前元素大的記錄都往后移動,用以騰出“自己”該插入的位置。當(dāng)n-1趟插入完成后就是需要的有序序列。

/**

 *直接插入排序算法

 */

void InsertSort(SqList *L){

    int i, j;

    for (i = 2; i < L->length; i++) {        

        if (L->r[i] < L->r[i-1]) { // 需要將 L->r[i] 插入有序子表            

            L->r[0] = L->r[i]; // 設(shè)置哨兵

            for (j = i-1; L->r[j] > L->r[0]; j++)

                L->r[j+1] = L->r[i]; // 記錄后移            

            L->r[j+1] = L->r[0]; // 插入到正確位置

        }

    }

}

5、希爾排序

希爾排序是對直接插入排序的改進排序算法。希爾排序又叫縮小增量排序。

原理:希爾排序是把記錄按下標(biāo)的一定增量分組,對每組使用直接插入排序算法排序;隨著增量逐漸減少,每組包含的關(guān)鍵詞越來越多,當(dāng)增量減至1時,整個文件恰被分成一組,算法便終止。屬于不穩(wěn)定排序算法。

/**

 *  希爾排序算法

 */

void shellSort(SqList *L){    

    int i,j;

    int increment = L->length;  // 增量初始值等于排序記錄

    do {

        increment = increment /3 +1;  // 增量序列

        for (i = increment + 1; i < L->length; i++) {

            if (L->r[i] < L->r[i-increment]) {  // 需要將 L->r[i] 插入有序增量子表

                L->r[0] = L->r[i];  // 用哨兵暫時存放 L->r[i]

                for (j = i - increment; i >0 && L->r[0] < L->r[j]; j -= increment)

                    L->r[j+increment] = L->r[j];  // 記錄后移, 查找插入位置

                L->r[j+increment] = L->r[0];  // 插入

            }

        }

    } while (increment > 1);  // 增量不大于 1 時停止循環(huán)

}

6、堆排序

堆排序(Heapsort)是指利用堆這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計的一種排序算法。堆積是一個近似完全二叉樹的結(jié)構(gòu),并同時滿足堆積的性質(zhì):即子結(jié)點的鍵值或索引總是小于(或者大于)它的父節(jié)點。

算法過程描述

1、將初始待排序關(guān)鍵字序列(R1,R2….Rn)構(gòu)建成大頂堆,此堆為初始的無序區(qū);

2、將堆頂元素R[1]與最后一個元素R[n]交換,此時得到新的無序區(qū)(R1,R2,……Rn-1)和新的有序區(qū)(Rn),且滿足R[1,2…n-1]<=R[n];

3、由于交換后新的堆頂R[1]可能違反堆的性質(zhì),因此需要對當(dāng)前無序區(qū)(R1,R2,……Rn-1)調(diào)整為新堆,然后再次將R[1]與無序區(qū)最后一個元素交換,得到新的無序區(qū)(R1,R2….Rn-2)和新的有序區(qū)(Rn-1,Rn)。不斷重復(fù)此過程直到有序區(qū)的元素個數(shù)為n-1,則整個排序過程完成。

堆排序是一種不穩(wěn)定的排序方法。

/**

 * 已知 L->r[s..m] 中記錄的關(guān)鍵字除L->r[s]之外均滿足堆的定義

 * 該函數(shù)調(diào)整L->r[s] 的關(guān)鍵字,使L->r[s..m]成為一個大頂堆

 */

void HeadAdjust(SqList *L, int s, int m){

    int temp, j;

    temp = L->r[s];    

    for (j = 2 *s; j <= m; j *= 2) {  // 沿關(guān)鍵字較大的孩子結(jié)點向下篩選  這里循環(huán)的條件j從 2*s 開始是因為利用了二叉樹的性質(zhì)5:由于這顆是完全二叉樹,當(dāng)前節(jié)點序號是 s ,其左孩子的序號一定是 2s, 右孩子的序號一定是 2s+1,它們的孩子當(dāng)然也是以 2 的位數(shù)序號增加,因此 j 變量才這樣循環(huán)。        

        if (j < m && L->r[j] < L->r[j+1])  // 1. j < m 說明它不是最后一個節(jié)點  2. L->r[j] < L->r[j+1]) 說明左孩子小于右孩子

            j++;  // j 為關(guān)鍵字中較大的記錄的下標(biāo)        

        if (temp >= L->r[j])

            break;  // rc應(yīng)插入在位置s上        

        L->r[s] = L->r[j];

        s = j;

    }    

    L->r[s] = temp;  // 插入

}

/**

 * 對順序表L進行堆排序

 */

void HeapSort(SqList *L){

    int i;    

    for (i = L->length / 2; i>0; i--)   // 把L中的r構(gòu)建成一個大頂堆

        HeadAdjust(L, i, L->length);    

    for (i = L->length; i > 1; i--) {

        swap(L, 1, i);  // 將堆頂記錄和當(dāng)前未經(jīng)排序子序列的最后一個記錄交換

        HeadAdjust(L, 1, i-1);  // 將L->r[1..i-1]重新調(diào)整為大頂堆

    }

}

7、歸并排序

歸并排序是建立在歸并操作上的一種有效的排序算法。該算法是采用分治法(Divide and Conquer)的一個非常典型的應(yīng)用。

實現(xiàn)原理(遞歸實現(xiàn)):

1、將序列平均分成兩部分

2、分別對這兩部分用遞歸來歸并

3、將這兩部分歸并到一起

算法示例

#p.歸并排序(遞歸實現(xiàn))

/**

 * 將有序的 SR[i..m] 和 SR[m+1..n]歸并為有序的 TR[i..n]

 */

void Merge(int SR[], int TR[], int i, int m, int n){

    int j, k, l;

    for (j = m+1, k = i; i <= m && j <= n; k++) { // 將SR中記錄有小到大歸并入TR

        if (SR[i] < SR[j])

            TR[k] = SR[i++];

        else

            TR[k] = SR[j++];

    }

    if (i <= m) {

        for (l=0; l <= m-i; l++)

            TR[k+l] = SR[i+l];  // 將剩余的SR[i..m]復(fù)制到TR

    }

    if (j <= n) {

        for (l=0; l <= n-j; l++)

            TR[k+l] = SR[j+l]; // 將剩余的SR[j..n]復(fù)制到TR

    }

}

/**

 *將SR[s..t]歸并排序為TR1[s..t]

 */

void MSort(int SR[], int TR1[], int s, int t){

    int m;

    int TR2[MAXSIZE+1];

    if (s == t) {

        TR1[s] = SR[s];

    }else{

        m = (s+t)/2; // 將SR[s..t]平分為SR[s..m]和SR[m+1..t]

        MSort(SR, TR2, s, m);   // 遞歸將SR[s..m]歸并為有序的TR2[s..m]

        MSort(SR, TR2, m+1, t); // 遞歸將SR[m+1..t]歸并為有序的TR2[m+1..t]

        Merge(TR2, TR1, s, m, t); // 將TR2[s..m]和TR2[m+1..t]歸并到TR1[s..t]

    }

}

/**

 *  對順序表L作歸并排序

 */

void MergeSort(SqList *L){

    MSort(L->r, L->r, 1, L->length);

}

歸并排序是一種比較占內(nèi)存,但是效率高且穩(wěn)定的算法。

8、快速排序

實現(xiàn)原理:

選取一個關(guān)鍵字,放到一個位置,使得它的左邊的值都比它小,右邊的值都比它大,這個關(guān)鍵字叫做樞軸(pivot)

然后分別對左邊和右邊進行排序。

#p快速排序

/**

 * 交換順序表 L 中子表的記錄,使軸記錄到位,并返回其所在位置

 * 此時在它之前的記錄均不大于它,在它之后的記錄均不小于它

 */

int partition(SqList * L, int low, int high){    

    int pivotkey;

    pivotkey = L->r[low];  // 用子表的第一個記錄作為樞軸記錄    

    while (low < high) {  // 從表的兩端交替地向中間掃描

        while (low < high && L->r[high] >= pivotkey)

            high --;

        swap(L, low, high);  // 將比樞軸小的記錄交換到低端        

        while (low < high && L->r[low] <= pivotkey)

            high++;

        swap(L, low, high);  // 將比樞軸大的記錄交換到高端

    }    

    return low;  // 返回樞軸所在位置

}

/**

 * 對順序表 L 中的子序列 L->r[low..high] 作快速排序

 */

void QSort(SqList *L, int low, int high){    

    int pivot;

    if (low < high) {

        pivot = Partition(L, low, high);  // 將L->r[low..high]一分為二,算出樞軸值pivot

        QSort(L, low, pivot-1);  // 對 低子表遞歸排序

        QSort(L, pivot+1, high); // 對 高子表遞歸排序

    }

}

/**

 * 對順序表 L 作快速排序

 */

void QuickSort(SqList *L){

    QSort(L, 1, L->length);

}

9、排序算法比較

              

10、排序算法總結(jié)

10.1 內(nèi)部排序

1、排序的記錄數(shù)量較少是,可以考慮插入排序和簡短選擇排序。如果記錄本身信息量較大時,建議選用選擇排序。

2、如果待排序記錄按關(guān)鍵字基本有序,適合采用冒泡排序或直接插入排序

3、若 排序記錄較大,可以選擇快速排序、堆排序或歸并排序。目前快速排序被認(rèn)為最好的排序方法。

10.2 外部排序

外部排序就是針對大型文件的排序。常用的外部排序方法是歸并排序。

IT技術(shù)分享社區(qū)

個人博客網(wǎng)站:https://

    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多