算法基礎:常用的排序算法知識筆記

1、算法外排序分類

?

? ? ? ?? ? ? ?

2、冒泡排序

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

實現算法:

/**

?* 冒泡排序優化后的算法

?* 設置一個標記來標志一趟比較是否發生交換

?* 如果沒有發生交換,則數組已經有序

?*/

void bubbleSort(SqList *L){

? ? int i,j;? ??

? ? int flag = true;? // flag 用來作為標記

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

? // 若flag為true 則說明數據交換過,否則沒交換過(數組已經有序) 則停止循環

? ? ? ? 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;? // 如果有數據交換 flag為true

? ? ? ? ? ? }

? ? ? ? }

? ? }

}

3、簡單選擇排序

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

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

/**

?* 簡單選擇排序算法

?*/

void selectSort(SqList *L){

? ? int i, j, min;

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

? ? ? ? min = i;? ? // 將當前下標定義為最小值下標

? ? ? ? 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)的是將一個記錄插入到已經排好序的有序表中,從而得到一個新的、記錄增1的有序表。

原理:將一個記錄插入到一個已經排序好的表中,得到一個記錄增加1的有序表。并且它把當前元素大的記錄都往后移動,用以騰出“自己”該插入的位置。當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]; // 設置哨兵

? ? ? ? ? ? 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、希爾排序

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

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

/**

?*? 希爾排序算法

?*/

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 時停止循環

}

6、堆排序

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

算法過程描述

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

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

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

?

堆排序是一種不穩定的排序方法。

?

/**

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

?* 該函數調整L->r[s] 的關鍵字,使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) {? // 沿關鍵字較大的孩子結點向下篩選? 這里循環的條件j從 2*s 開始是因為利用了二叉樹的性質5:由于這顆是完全二叉樹,當前節點序號是 s ,其左孩子的序號一定是 2s, 右孩子的序號一定是 2s+1,它們的孩子當然也是以 2 的位數序號增加,因此 j 變量才這樣循環。? ? ? ??

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

? ? ? ? ? ? j++;? // j 為關鍵字中較大的記錄的下標? ? ? ??

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

? ? ? ? ? ? break;? // rc應插入在位置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構建成一個大頂堆

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

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

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

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

? ? }

}

7、歸并排序

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

實現原理(遞歸實現):

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

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

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

算法示例

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

/**

?* 將有序的 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]復制到TR

? ? }

? ??

? ? if (j <= n) {

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

? ? ? ? ? ? TR[k+l] = SR[j+l]; // 將剩余的SR[j..n]復制到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);

}

歸并排序是一種比較占內存,但是效率高且穩定的算法。

?

?

8、快速排序

實現原理:

選取一個關鍵字,放到一個位置,使得它的左邊的值都比它小,右邊的值都比它大,這個關鍵字叫做樞軸(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、排序算法總結

10.1 內部排序

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

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

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

10.2 外部排序

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

?

IT技術分享社區

個人博客網站:https://programmerblog.xyz

文章推薦程序員效率:畫流程圖常用的工具程序員效率:整理常用的在線筆記軟件遠程辦公:常用的遠程協助軟件,你都知道嗎?51單片機程序下載、ISP及串口基礎知識硬件:斷路器、接觸器、繼電器基礎知識

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/271659.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/271659.shtml
英文地址,請注明出處:http://en.pswp.cn/news/271659.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

302狀態碼_http狀態碼是什么?301 302 404的SEO應用場景

什么是HTTP狀態碼&#xff1f;簡單的講&#xff0c;就是用以表示網頁服務器HTTP響應狀態的3位數字代碼。其中1xx表示臨時響應&#xff0c;2xx表示成功處理了請求&#xff0c;3xx代表重定向&#xff0c;4xx表示請求錯誤&#xff0c;而5xx表示服務器錯誤。除了網頁正常返回200之外…

Android高版本開機廣播,android3.1以上,假如程序沒有啟動過,怎么獲取開機廣播呢?...

官方說不支持&#xff1a;Launch controlson stopped applicationsStarting from Android 3.1, the systems package manager keepstrack of applications that are in a stopped state and provides ameans of controlling their launch from background processes andother a…

git push前請先git pull

開發過程中 如果要推送代碼到遠程倉庫&#xff0c;請先git pull。養成好習慣。 原因很簡單&#xff0c;在你開發過程中&#xff0c;你的同事可能也在改代碼然后他提交了沒通知你&#xff0c;你直接git push很容易造成代碼沖突&#xff0c;代碼沖突解決也簡單&#xff0c;可萬一…

table 中 thead tbody tfoot 加載順序問題

這幾個標記主要是用于提高table標簽的加載以及顯示的&#xff0c;說白了&#xff0c;就是分布加載。在傳統的瀏覽器&#xff0c;在加載 時&#xff0c;是當所有的標簽中元素都被下載后才會顯示&#xff0c;當然這樣的用戶體驗是不好的。再加入了這幾個t打頭的標簽后&#xff0c…

算法基礎:常用的查找算法知識筆記

1、查找表和查找效率的概念查找表是指由同一類型的數據元素構成的集合。分為靜態查找表和動態查找表。1.1 靜態查找表1、查詢某個特定元素是否在查找表的集合當中2、查詢某個特定元素的各種屬性1.2 動態查找表1、在查找表中插入一個數據元素2、在查找表中刪除一個元素1.3 關鍵字…

注解參數怎么使用變量_硅橡膠膠水有哪些特點?使用參數表現的怎么樣?如何儲存?...

作為單組分產品&#xff0c;硅橡膠膠水的使用方法簡單又靈活。直接涂抹在粘接基面上&#xff0c;固化之后即可抵抗外界的壓力與沖擊。別看它的規格不是很打&#xff0c;卻可以順順利利完成粘接&#xff0c;形成保護膜。硅橡膠膠水有哪些特點?沒有固化之前&#xff0c;是半透明…

android 谷歌郵箱,Android 使用 SMTP 發送郵件 (Gmail)

具體使用方法請看&#xff1a;http://www.oschina.net/code/snippet_12_9831.[代碼]GMailSender.javapackage org.apache.android.mail;import javax.activation.DataHandler;import javax.activation.DataSource;import javax.mail.Message;import javax.mail.PasswordAuthent…

Java中return的兩種用法

一、return語句總是用在方法中&#xff0c;有兩個作用。 一個是返回方法指定類型的值&#xff08;這個值總是確定的&#xff09;。 一個是結束方法的執行&#xff08;僅僅一個return語句&#xff09;。 一般的就百是用在有反回值的方法中&#xff0c;用來返回方度法指定問類…

Alpha版總結會議

一、會議過程 我們于第十五周周一開始在學院樓針對前一段時間開發過程中的問題進行了討論。會議期間我們整合并回顧了一下兩次沖刺周期的成果。會議開始首先每個人都先發表了自己針對Alpha版開發過程中存在的疑惑和一些問題的看法。我們最后挑選出出三個最具針對性的問題進行了…

算法基礎:遞歸算法知識筆記

1、遞歸算法定義遞歸算法是將重復問題分解為同類的子問題而解決問題的方法&#xff0c;其核心思想是分治策略。簡單來說就是自己調用自己。直到達到退出遞歸的條件&#xff0c;則完成遞歸。2、遞歸的步驟1、找整個遞歸的終止條件&#xff1a;遞歸應該在什么時候結束&#xff1f…

ttl繼承邏輯門的邏輯功能與參數測試 實驗總結_LMS電聲測試儀,LMS-V測試系統,精聲電聲...

LMS-V測試系統LMS揚聲器測試儀從推出到現在25年的時間&#xff0c;在全世界被很多揚聲器開發與制造廠家廣泛應用研發與生產質量控制&#xff0c;傳統的LMS揚聲器測試儀采用ISA卡的形式提供&#xff0c;所以面臨著越來越多的零件過時&#xff0c;所以為了徹底解決這些問題&#…

android自動讓輸入框上劃,Android界面技巧:當輸入法調出時,如何讓界面自動上移,使輸入法不會遮擋到主界面(Activity)...

android:windowSoftInputModeactivity主窗口與軟鍵盤的交互模式&#xff0c;可以用來避免輸入法面板遮擋問題&#xff0c;Android1.5后的一個新特性。這個屬性能影響兩件事情&#xff1a;【一】當有焦點產生時&#xff0c;軟鍵盤是隱藏還是顯示【二】是否減少活動主窗口大小以便…

java中break標記的使用

筆試題目&#xff1a;break目前位于內層的for循環&#xff0c;如何才能讓break作用于外層 的for循環。可以標記解決 標記的命名只要符合標識符的命名規則即可。 Test public void test2(){aaa:for(int j 0 ; j<3 ; j){ // j0 外層for循環for(int i 0 ; i< 2 ; i){ //…

六月計劃#2B(6.10-6.16)

4/7 STL set 數學 快速傅立葉(FFT)高斯消元動態規劃 斜率優化轉載于:https://www.cnblogs.com/Sunnie69/p/5573299.html

電腦基礎知識入門:鍵盤上的英文,意思和功能匯總!

電腦鍵盤是把文字信息的控制信息輸入電腦的通道&#xff0c;從英文打字機的鍵盤演變而來的。它最早出現在電腦上的時候&#xff0c;還是一種叫做“電傳打字機”的部件。那些陌生的鍵盤按鍵都有什么用途?很多孩子不知道鍵盤上功能鍵和字母數字鍵以外的鍵盤按鍵有什么用&#xf…

elementui el-dialog 離頂部的位置_駐馬店建筑物避雷帶的安裝位置,本月報價

首頁 > 新聞中心發布時間&#xff1a;2020-11-06 18:23:42 導讀&#xff1a;科杰防雷為您提供駐馬店建筑物避雷帶的安裝位置的相關知識與詳情&#xff1a; 該系統在正常運行時&#xff0c;不管三相負荷平衡不平衡&#xff0c;在中性線N帶電情況下&#xff0c;PE線不會帶電。…

android 彈出框帶標題欄,Android開發靠標題欄的彈框

一、效果圖title_dialog.png二、思路首先它是一個彈框&#xff0c;只是彈框的布局做些處理&#xff0c;布局占滿屏幕&#xff0c;只有需要白色的布局的背景設為白色。其他沒設置背景顏色&#xff0c;自然用dialog的style的windowBackground三、案例關鍵代碼dialog的xmlxmlns:ap…

算法基礎:圖的相關算法知識筆記

一、圖的相關算法1、圖的分類知識如下圖&#xff1a;2、生成樹概念對連通圖進行遍歷&#xff0c;過程中所經過的邊和頂點的組合可看做是一棵普通樹&#xff0c;通常稱為生成樹。連通圖的生成樹具有這樣的特征&#xff1a;邊的數量 頂點數 - 13、最小生成樹在連通網的所有生成樹…

下午回來才后知百密于一疏忽

交了1700定金后就去了中介公司看了一下&#xff0c;比較偏僻窄小&#xff0c;然后里面有一些人和辦公桌比較擠&#xff0c;中介“董楠楠”介紹了一下女經理&#xff0c;然后就做地鐵回了&#xff0c;中途記憶&#xff0c;沒有冰箱然后統一口徑&#xff0c;對于只有一個電磁爐的…

java中break和continue的用法例子

break用于switch語句 1. break用于switch語句中&#xff0c;終止switch語句 下面先看 加上break,效果如下 我們可以看到&#xff0c;沒有用過break關鍵字時&#xff0c;不會在判斷下一個case的值&#xff0c;直接向后運行&#xff0c;直到遇到break&#xff0c;或者整體swit…