排序演算法(天勤資料結構高分筆記)

2021-09-01 11:43:21 字數 3743 閱讀 2047

排序演算法

直接插入排序演算法:每趟將乙個待排序的關鍵字按照其值的大小插入到已經排好的部分有序序列的適當位置上,直到所有待排關鍵字都被插入到有序序列中為止

void insertsort(int r, int n)    //代拍關鍵字儲存在r中,預設為整形,個數為n

r[j + 1] = temp;    //找到插入位置,將temp中暫存的待排關鍵字插入

}}//直接插入演算法的時間複雜度為o(n*n)

希爾排序:希爾排序又稱之為縮小增量排序,其本質還是插入排序,只不過是將待排序列按照某種規則分成幾個子串行

,分別對這幾個子串行進行直接插入排序。這個規則的體現就是增量的選取.希爾排序的時間複雜度為o(n*logn)

void shellsort(int array, int n)

array[j + d] = temp;}}

d = d / 2;    //縮小增量

}}

//氣泡排序:時間複雜度為o(n*n)

void bubblesort(int r, int n)        //預設待排序關鍵字為整型

if (0 == flag)    //一趟排序過程中如果沒有發生關鍵字交換,則證明序列有序,排序結束

return;

}}

快速排序;也是交換類的排序,它通過多次劃分操作實現排序。以公升序為例,其執行流程可以概括為:每一趟選擇當前所有子串行中的乙個關鍵字(通常是第乙個)作為樞軸,將子串行中比樞軸小的移到樞軸的前邊,比樞軸大的移動到樞軸的後邊;當本趟所有的子串行都被樞軸以上述規則劃分完畢後會的到新的一組更短的子串行,它們成為下一趟劃分的初始序列集。快速排序的演算法思想基於分治思想的,其平均時間複雜度為o(n*logn),最壞時間複雜度為o(n*n)

void quicksort(int r, int low, int high)    //對從r[low]到r[high]的關鍵字進行排序

while (i < j && r[i] <= temp)    //從右往左掃瞄,找到乙個大於temp的關鍵字

++i;

if (i < j)

}r[j] = temp;    //將temp放在最終的位置上

quicksort(r, low, i - 1);    //遞迴的對temp左邊的關鍵字進行排序

quicksort(r, i + 1, high);    //遞迴的對temp右邊的關鍵字進行排序

}}

簡單選擇類排序:選擇類排序的主要動作是「選擇」。簡單選擇採用最簡單的選擇方式,從頭至尾掃瞄序列,選出

最小的乙個關鍵字,和第乙個關鍵字交換,接著從剩下的關鍵字中繼續這種選擇和交換,最終使序列有序

void selectsort(int r, int n)

//下面三句完成最小關鍵字與無序序列的第乙個關鍵字的交換

temp = r[i];

r[i] = r[k];

r[k] = temp;

}}

堆排序:對是一種完全二叉樹,這顆二叉樹滿足:任何乙個非葉結點的值都不大於(或小於)其左右孩子結點的值。若父親大孩子小,這樣的堆稱之為大頂堆;若父親小孩子大稱為小根堆。

根據堆的定義可以知道,代表堆的這顆完全二叉樹的根結點是最大的(或者最小的),因此將乙個無序的序列調整為乙個堆,就可以找到這個序列的最大值(或者最小)的值,然後將找出的值交換到這個序列的最後(或最前),這樣有序序列關鍵字增加1個,無序序列中的關鍵字減少1個,對新的無序序列重複這樣的操作,就實現了排序。這就是堆排序的思想

堆排序中最關鍵的操作是將序列調整為堆。整個排序的過程就是通過不斷調整,使得不符合堆定義的完全二叉樹變為符合堆定義的完全二叉樹

堆的插入關鍵字:需要在插入結點之後保持堆的性質,即完全二叉樹形態與父大子小性質(以大根堆為例),因此需要先將要插入的結點x放在最底層的最右邊,插入後滿足完全二叉樹的特點,然後把x依次向上調整到合適位置上以滿足父大子小的性質

堆中刪除結點:刪除堆中乙個結點時,原來的位置就會出現乙個孔,填充這個孔的方法就是:把最底層最右邊的葉子值賦給該孔並下調到合適的位置,最後把

該葉子結點點刪除堆排序執行過程描述(以大根堆為例):

1)從無序序列所確定的完全二叉樹的第乙個非葉子結點開始,從左至右,從上至下,對每個結點進行調整,最終得到乙個大根堆

對結點的調整方法:將當前結點(假設為a)的值與其孩子結點進行比較,如果存在大於a的值的孩子結點,則從中挑出最大的乙個與a進行交換。當a來到

下一層的時候重複上述過程,直到a的孩子結點的值都小於a的值為止。

2)將當前的無序序列中的第乙個關鍵字,反應在樹的根結點(假設為b)與無序序列中的最後乙個關鍵字交換(假設為c)。b進入有序序列,達到最終位置。

無序序列中的關鍵字個數減少1個,有序序列中的關鍵字個數增加1個,此時只有結點c可能不滿足堆的定義,對其進行調整

3)重複上述第2)步,直到無序序列中的關鍵字個數為1時結束排序

**如下:

//本函式完成在陣列r[low]到r[high]的範圍內對在位置low上的結點進行調整

void sift(int r, int low, int high)//這裡關鍵字的儲存設定為從陣列下標為1開始

else break;

}r[i] = temp;            //被調整結點的值放入最終位置

}//堆排序函式

void heapsort(int r, int n)

堆排序演算法所需的空間複雜度為o(1),這是它相對於歸併排序的優點。時間複雜度在任何情況下均為o(n*logn),這是它相對於快速排序的最大優點, 快速排序最壞的時間複雜度為o(n*n)。

堆排序適用場景是關鍵字數目特別多的情況下,典型的例子是從10000個關鍵字選出前10個最小的。這種情況下用堆排序最好。如果關鍵字數目較少,則不建議使用堆排序

//stl中已經寫好了堆排序,一般如果是自己在實踐中需要用的是由直接呼叫下面兩句即可

make_heap(_first, _last, _comp);    //預設是建立最大堆的。對int型別,可以在第三個引數傳入greater()得到最小堆。

sort_heap(_first, _last);            //排序之後就不再是乙個合法的heap了

make_heap(b, b + 10 ,greater());    //建立小根堆

sort_heap(b, b + 10, greater());    //從大到小進行排序

make_heap()建堆的時候,預設是大根堆,第三個引數用greater會變成小根堆;

sort_heap()排序的時候,預設是從小到大,但是第三個引數用greater會變成從大到小

並且sort_heap的第三個引數要和make_heap的第三個引數一致,否則程式執行時會報錯

//上面這兩個函式原型為:

template void make_heap (randomaccessiterator first, randomaccessiterator last);

template void make_heap (randomaccessiterator first, randomaccessiterator last,

compare comp );

templateinline

void sort_heap(_ranit _first, _ranit _last)

*/

天勤計算機考研高分筆記(一)緒論1資料結構

1.1.1 答題規則,技巧 1.演算法設計題中的 部分,只需要寫出乙個或者多個可以解決問題的有著清楚介面描述的函式即可。定義1.介面 為使用者和函式打交道的地方,通過介面,使用者輸入自己的資料,得到想要的結果。eg count error struct typea typea 是新的資料型別 1.1...

《資料結構高分筆記》讀書筆記

說明 當年看完 資料結構高分筆記 2014版,吸收精華後寫了乙份讓我引以為豪的精簡筆記。然而現在掉了。找到不到了。痛心。為了鞏固資料結構,不得已再拾起這本書再過一遍。這回筆記不再寫在紙上了。第一章 緒論 資料型別 結構型即使用者自己製作的資料型別 typedef 用來給現有的資料型別起乙個新名字,新...

天勤考研資料結構 單鏈表操作

定義單鏈表 typedef struct lnodelnode a b皆為有序鍊錶,合併排序到c中 頭插法 void merge lnode a,lnode b,lnode c else if q next null if p null if p next null if q null a b皆為有...