ACM基礎之排序演算法

2021-07-24 09:36:20 字數 3049 閱讀 1823

在acm基礎知識中,排序是一種比較基礎但又比較重要的思想,熟練地掌握排序演算法十分有必要。排序的方法比較多,這裡重要介紹三種排序:選擇排序、插入排序、氣泡排序。

一、選擇排序

1、基本思想:在要排序的一組數中,選出最小的數與第乙個數交換,然後再在剩下的數中選出最小的數與第二個數交換….直到第n-1個數與第n個數比較為止;

例:3 1 5 2 4

第一步,選出這五個數中最小的數,即 1;

第二步,將1與此陣列的第乙個數3交換,此時陣列為:1 3 5 2 4;

第三步,在後四個數中選出最小的數,即 2;

第四步,將 2 與 3 交換,此時陣列為:1 2 5 3 4;

第五步,以此類推,將3與5交換,此時陣列為:1 2 3 5 4;

第六步,將4與5交換,此時陣列為:1 2 3 4 5,排序完畢。

2、**詳解:

#include

int main()

for(int l=0;l<10;l++)

printf("%d ",array[l]);

printf("\n");

}

這裡預設了10個數排序,在排序的for迴圈裡(大家應該能看出來哪個是用來排序的for迴圈),外層的for迴圈代表著從第乙個數開始比較直到比較到最後乙個,然後把 i 賦值給k,也就是說現在array[k]的值和array[i]的值相等,從第 i+1個數的後乙個數開始比較,如果發現array[j]比array[k]小,那麼就把 j 賦值給k,然後繼續比較,直到最後乙個數為止。也就是說,在執行完11、12、13行的**之後,array[k] 中儲存的應該是剩下的所有數中最小的數了。就算array[i] 就是最小值的話,那麼array[k]中儲存的也應該是array[i] 的值。所以,在14、15、16行中,將array[k]和array[i]交換。

二、插入排序

1、基本思想:將乙個元素插入到乙個已經排序好的有序表中,從而得到乙個新的、記錄數增1的有序表。即:先將序列的第1個記錄看成是乙個有序的子串行,然後從第二個記錄逐個進行插入,直到整個序列有序為止;

例:3 1 5 2 4

第一步:先將3預設為乙個排序好的序列;

第二步:將1 插入該有序表,將1 插在3的前面,此時該有序表為 1 3;

第三步:將5 插入該有序表,將5插在3的後面,此時該有序表為 1 3 5;

第四步:將2插入該有序表,將2插在1 和 3 中間,此時有序表為 1 2 3 5;

第五步:將4插入該有序表,將4插在3 和 5 中間,此時有序表為 1 2 3 4 5,排序完畢。

2、**詳解:

#include

int main()

a[p+1] = temp; //將該位置的值覆蓋

}for(int j = 0;j<10;j++) //輸出

printf("%d ",a[j]);

}

這裡依然預設了十個數的排序,第8行到18行**為排序**。由於對於陣列中的第乙個數我們預設它為乙個排好序的有序表,所以我們從第二個數開始進行插入操作。對於陣列中的第 i + 1個數,也就是a[i],我們先將a[i] 賦值給temp,然後從第i個數,即a[i-1]開始比較。

注意while迴圈中的條件,p>=0 && temp < a[p]。我們在這裡假設我們要將4 插入 1 2 3 5這個有序表中,及將a[4]插入到這個表中,讓a[4] ,即temp= 4先與 a[3] = 5比較,發現符合條件,執行while迴圈:把a[3]賦值給a[4],即a[4] = 5,也就是把5 向後移乙個位置,然後p–也就此時p = 2;然後將temp = 4與a[2] = 3比較,發現不符合條件。則a[p+1] = a[2+1] = a[3] = 4,插入完畢。而對於將1插入到3這個有序表中這個操作,在第一次執行完while迴圈之後,p = -1。然後再執行while迴圈的時候,發現p不大於等於0 ,即不符合條件,所以a[-1+1] = a[0] = 1,插入完畢。

三、氣泡排序

1、基本思想:通過無序區中相鄰記錄關鍵字間的比較和位置的交換,使關鍵字最小的記錄如氣泡一般逐漸網上「漂浮」,直至「水面」;

例:3 1 5 2 4

第一步:從後往前比較,將2 和4 比較發現2 < 4 不需要交換;

第二步:隨後比較5 和 2,發現5 < 2,交換,序列變成3 1 2 5 4;

第三步:比較1 和 2 ,發現 1 < 2,不需要交換;

第四步:比較3 和 1,發現 3 > 1,交換,序列變成1 3 2 5 4,至此第乙個大的迴圈結束;

第五步:再從最後開始,比較5 和 4,交換,序列變成 1 3 2 4 5;

第六步:比較2 和 4,不需要交換;

第七步:比較3 和 2,交換,序列變成1 2 3 4 5,排序結束。

2、**詳解:

#include

int main()

}for(int i=0;i<=9;i++) //輸出

printf("%d ",a[i]);

}

思考一下:對於乙個有n個元素的序列,最多需要多少個大的迴圈呢?

答案是n-1。這是為什麼呢?設想,乙個氣泡排序,最「慘烈」的情況就是:第一次大的迴圈,把最小的數「冒」到最前面,第二次大的迴圈,把第2小的數「冒」到前面….一直到第n-1次迴圈,把n-1「冒」到前面。而當n-1已經在它的位置上的時候,n自然已經在最後的位置了。所以在第7到第17行**中,最外層的迴圈一共要進行9次,即n-1次(在這裡n預設為10),然後j從8開始迴圈,如果前面的數比後面的大,那麼交換兩個元素的位置。

這裡外層迴圈進行了n-1次,這是為了取最大值,其實還有一種寫法,那就是當檢測到一次大的迴圈已經沒有元素發生互換之後,就可以中止迴圈了。**的實現這裡不再給出。

以上大概就是三種排序的思想及**實現。其實,這三種排序的結果並不重要,但是這種演算法、這種思想大家一定要會,**一定要會寫。其實如果單單就排序的結果而言,c++函式中的sort函式要快捷得多,也方便得多,但是一些題目中,你不會這種排序思想是寫不出來的,所以了解這些排序思想,對於我們的acm之路還是很有必要的

ACM基礎(四) 排序之快速排序

二 c 實現 快速排序,也是分治法。意義 就是通過pivot將陣列分成兩部分,前面的一部分小於等於pivot,後面的一部分大於pivot。將倒數第一作為 軸 pivot 建立兩個哨i 開始再往前乙個 i 1表示大於pivot的元素 j 遍歷的 從開始到倒數第二 表示當前小於等於pivot的元素 遍歷...

ACM 快速排序演算法

每次以陣列第乙個數為基數,從陣列兩端往中間找,小於基數的數放在陣列的左邊,大於它的數放在陣列的右邊,當i j的時候,查詢結束,將基數賦值到這個位置,這個數在陣列中的位置就是這個,確定了。然後從這個數的左邊和右邊開始遞迴,直到所有的數都排完序。時間複雜度 nlog2n 最好,平均 n2 最壞 incl...

ACM道路之一 基礎演算法(快速排序)

快速排序 qsort 本質是分治思想 排序的一次劃分演算法從兩頭交替搜尋,直到low和high重合,因此其時間複雜度是o n 而整個快速排序演算法的時間複雜度與劃分的趟數有關。快速排序三個步驟 1 確定區域,左邊界 l 右邊界 r 基準值 x l r 2 2 保證區間內,x左側的任意值小於x,x右側...