借助一道題來練習排序演算法:
(從小到大)氣泡排序是每次比較相鄰的兩個元素大小,如果第乙個比第二個大,交換位置,直到末尾。每次到達末尾之後當前元素作為新的末尾進行下一次冒泡。直到再也沒有需要交換的。
演算法實現:
/**
* note: the returned array must be malloced, assume caller calls free().
*/void
swap
(int
*a,int
*b)void
bubblesort
(int
*nums,
int numssize)}if
(1== is_sorted)
break
;//陣列本來就有序,返回}}
int*
sortarray
(int
* nums,
int numssize,
int* returnsize)
優化:
基於最基本的氣泡排序,做了以下幾點優化:
選擇排序是一種簡單直觀的排序演算法,無論什麼資料進去都是 o(n²) 的時間複雜度。所以用到它的時候,資料規模越小越好。唯一的好處可能就是不占用額外的記憶體空間了吧,在鍊錶情況下使用比較穩定。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。重複第二步,直到所有元素均排序完畢。
分為兩部分,前半部分是已排序部分,後半部分是未排序部分,後面逐步將未排序部分的最小值找出依次放在已排序後面,作為已排序部分新的最大值。
選擇排序的特點:
①、執行時間和輸入無關。為了找出最小的元素而掃瞄一遍陣列並不能為下一遍掃瞄提供什麼資訊;
②、資料移動是最小的。每次交換都會改變兩個陣列元素的值,因此選擇排序用了 n 次交換——交換次數和陣列的大小是線性關係。(其他大部分排序演算法的增長數量級都是線性對數或是平方級別的)
基礎演算法實現:
void
selectionsort
(int
*nums,
int numssize)
}swap
(&nums[min]
,&nums[i]);
}}
插入排序和選擇排序實現有些類似,都是分為已排序部分和未排序部分來看的,選擇排序是每次選出未排序部分的最小值作為已排序部分的最大值。插入排序是在未排序部分中,依次排序,每次看乙個元素,將此元素與已排序部分比較,直到找到在已排序部分中的位置。
插入排序,可以理解為插隊式排序,從最後面依次尋找可插隊的物件,對於比自己大的值,不敢在它面前插隊,一旦遇到比自己小的值,就立刻插隊。
演算法實現:
/* 插入排序 */
void
insertsort
(int
*num,
int numssize)
num[j +1]
= key;
//插入到適合的位置
}}
要注意,while
判斷中(j >= 0)
的優先順序要比後面的高,不然可能造成記憶體洩漏問題!!!
插入排序很循規蹈矩,不管陣列分布是怎麼樣的,依然一步一步的對元素進行比較,移動,插入,但是插入排序在陣列基本有序的情況下效率是很高的。
希爾排序是希爾(donald shell)於2023年提出的一種排序演算法。希爾排序也是一種插入排序,它是簡單插入排序經過改進之後的乙個更高效的版本,也稱為縮小增量排序,同時該演算法是衝破o(n2)的第一批演算法之一。
希爾排序是插入排序的高階優化。利用的就是插入排序在陣列基本有序的情況下效率很高的優點,先對陣列進行大塊的插入排序,使陣列基本有序,再對基本有序的陣列使用插入排序。
該方法的基本思想是:先將整個待排元素序列分割成若干個子串行(由相隔某個「增量」的元素組成的)分別進行直接插入排序,然後依次縮減增量再進行排序,待整個序列中的元素基本有序(增量足夠小)時,再對全體元素進行一次直接插入排序。因為直接插入排序在元素基本有序的情況下(接近最好情況),效率是很高的,因此希爾排序在時間效率上比前兩種方法有較大提高。
通俗來講,希爾排序就是一層一層插入排序疊加起來的。
圖示:
演算法實現:
/* 希爾排序 */
void
shellsort
(int
*num,
int numssize)
num[j + gap]
= key;}}
}
還有一種基於優化插入方法的希爾排序:
/* 基於優化插入的 希爾排序 */
void
shellsort3
(int a,
int n)
歸併排序的核心思想就是兩個有序陣列,像出棧一樣比較各自前面的元素,將比較的結果按順序放在乙個新的陣列中,這個新的陣列中最後就是兩個陣列最終排序好的。
歸併操作的工作原理如下:
第一步:申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合併後的序列
第二步:設定兩個指標,最初位置分別為兩個已經排序序列的起始位置
重複步驟3直到某一指標超出序列尾
將另一串行剩下的所有元素直接複製到合併序列尾
每日一題 第二十二題
第二十二題 韓信點兵 在中國數學史上,廣泛流傳著乙個 韓信點兵 的故事 韓信是漢高祖劉邦手下的大將,他英勇善戰,智謀超群,為漢朝建立了卓越的功勞。據說韓信的數學水平也非常高超,他在點名的時候,為了知道有多少兵,同時又能保住軍事機密,便讓士兵排隊報數 按從1到5報數,記下最末乙個士兵報的數為1 按從1...
每日一題 1
題目詳情 peter喜歡玩數字遊戲,但數獨這樣的遊戲對他來說太簡單了,於是他準備玩乙個難的遊戲。遊戲規則是在乙個n n的 裡填數,規則 對於每個輸入的n,從左上角開始,總是以對角線為起點,先橫著填,再豎著填。這裡給了一些樣例,請在樣例中找到規律並把這個n n的 列印出來吧。輸入描述 多組測試資料 資...
每日一題2018 3 21
leetcode 2 模擬十進位制運算考察單鏈表基本操作。題無難點,個人基礎需要提高。definition for singly linked list.struct listnode class solution while p while q if shi val s next null ret...