一、排序算法的概念
????????排序(Sorting)是指:將一組“無序”的數據,按照某種“順序規則”排列成“有序”的過程。
1、按排序順序分類:
????????升序:從小到大排列,如 1, 3, 5, 7, 9
降序:從大到小排列,如 9, 7, 5, 3, 1
2、按排序方式分類:
分類方式 | 排序類型 | 簡要說明 |
---|---|---|
內部排序 | 冒泡、插入、選擇、歸并、快速等 | 所有數據在內存中進行排序 |
外部排序 | 多路歸并排序 | 數據量過大時,需借助外部存儲 |
二、 常見的排序算法及其特點
排序算法 | 時間復雜度(平均) | 空間復雜度 | 是否穩定 | 適用場景 |
---|---|---|---|---|
冒泡排序 | O(n2) | O(1) | 穩定 | 小規模數據、教學演示 |
選擇排序 | O(n2) | O(1) | 不穩定 | 數據量小、對穩定性要求不高 |
插入排序 | O(n2) | O(1) | 穩定 | 基本有序數據、鏈表排序 |
歸并排序 | O(n log n) | O(n) | 穩定 | 大數據排序、需要穩定性 |
快速排序 | O(n log n) | O(log n) | 不穩定 | 實際中最常用,效率高 |
堆排序 | O(n log n) | O(1) | 不穩定 | 不要求穩定性的高效排序 |
計數排序 | O(n + k) | O(k) | 穩定 | 數據范圍小的整數排序 |
桶排序 | O(n + k) | O(n + k) | 穩定 | 分布均勻的數據 |
基數排序 | O(nk) | O(n + k) | 穩定 | 位數較小的整數/字符串 |
三、排序算法的應用場景
數據庫系統:
排序是實現?ORDER BY?的核心
排序有助于數據壓縮和索引創建
搜索優化:
排序之后可以使用二分查找,大幅提高搜索效率
數據分析和可視化:
排序能幫助找出最大/最小值、前 K 大數等
排序數據更容易圖表化展示
去重和統計:
? ? ? ? ? 排序后相同數據聚集在一起,方便統計頻率或去重
工程開發:
? ? ? ? ? 排序是實現自動推薦、頁面排名、調度優化等系統的基礎
四、常用排序算法的實現
? ? ? ? 1、冒泡排序🫧
? ? ? ? 不斷比較鄰近的元素,將大元素右移,最終排成升序序列
代碼實現:
void Swap(int* p,int* q){assert(p&&q);int tmp = *p;*p = *q;*q = tmp;return; }void Bubble_sort(int* arr,int size){assert(arr);int end = size-1;int flag = 0;for (int i = 0;i<end;i++){for(int j = 0;j<end-i;j++){if(arr[j]>arr[j+1]){Swap(&arr[j],&arr[j+1]);flag = 1;}}if(flag == 0){break;}}return; }//測試函數 int main(){int arr[]= {6,2,8,10,1,3,5,12,4};Bubble_sort(arr,9);for(int i = 0;i<9;i++){printf("%d ",arr[i]);} }
冒泡排序的時間復雜度為,空間復雜度
。
2、插入排序
????????將數組的每個元素與所在位置之前的元素比較,找到升序(降序)位插入即可。
代碼實現:
void Insert_Sort(int* arr,int size){assert(arr);for (int end = 1;end<size;end++){for(int j = end-1;j>=0;j--){if(arr[j+1]<arr[j]){Swap(&arr[j],&arr[j+1]);}else{break;}}} }int main(){int arr[]= {6,2,8,10,1,3,5,12,4};// Bubble_sort(arr,9);Insert_Sort(arr,9);for(int i = 0;i<9;i++){printf("%d ",arr[i]);} }
插入排序的時間復雜度為
,空間復雜度
。
3、希爾排序的基本思想
希爾排序的提出者是 Donald Shell(1959 年),它是第一個突破 O(n2)?時間復雜度的排序算法。
核心思想:
將原始數組按照某個間隔 gap 進行“分組”,每組分別進行插入排序,然后逐步減小 gap,最終 gap = 1 時再進行一次插入排序,完成排序。
希爾排序的步驟說明(以升序為例)
選擇一個初始間隔 gap,通常是數組長度的一半,如?gap = n/2
將數組劃分為?gap?個子序列(組內元素間隔為 gap)
對每個子序列進行插入排序
縮小 gap:gap = gap / 2
重復步驟 2~4,直到?gap = 1
思維導圖
代碼實現:
void Shell_Sort(int* arr,int size){assert(arr);int gap = size;while(gap > 1){gap = gap/3+1;for (int end = gap;end<size;end++){int j = end-gap;int tmp = arr[end];while (j>=0 && arr[j]>tmp){arr[j+gap] = arr[j];j -= gap;}arr[j+gap] = tmp;} } }
希爾排序的時間復雜度:最壞情況視 gap 序列而定,常見為 O(n^(1.3 ~ 2)),比 O(n2) 快很多
希爾排序的特點
特性 | 描述 |
---|---|
時間復雜度 | 最壞情況視 gap 序列而定,常見為 O(n^(1.3 ~ 2)),比 O(n2) 快很多 |
空間復雜度 | O(1)(原地排序) |
穩定性 | 不穩定排序(可能打亂相同元素順序) |
應用場景 | 中等規模、內存受限的排序任務 |
希爾排序與插入排序的對比
項目 | 插入排序 | 希爾排序 |
---|---|---|
排序速度 | 慢(O(n2)) | 快(改進版插排) |
數據交換次數 | 多 | 少 |
排序思想 | 比較相鄰元素 | 比較“間隔 gap”的元素 |
應對無序數據 | 效率低 | 效率更高 |
好了本期的排序算法內容分享就到這里結束了,謝謝大家的點贊收藏