常見排序算法深度評測:從原理到10萬級數據實戰

常見排序算法深度評測:從原理到10萬級數據實戰

摘要
本文系統解析冒泡排序、選擇排序、插入排序、希爾排序、歸并排序、快速排序、堆排序和基數排序8種經典算法,通過C語言實現10萬隨機數排序并統計耗時。測試顯示:快速排序綜合性能最優(0.12秒),冒泡排序最慢(32.7秒)。算法效率差異顯著,時間復雜度從 O ( n 2 ) O(n^2) O(n2) O ( n log ? n ) O(n\log n) O(nlogn)不等。文中提供完整代碼實現、時間復雜度對比表及場景選擇建議,為工程實踐提供直接參考。


在這里插入圖片描述


一、算法原理與實現

1. 冒泡排序

原理:通過相鄰元素比較交換,使最大元素逐漸"浮"到數組末端
時間復雜度 O ( n 2 ) O(n^2) O(n2)

#include <stdio.h>
#include <stdlib.h>
void bubbleSort(int arr[], int n) {for (int i = 0; i < n-1; i++)for (int j = 0; j < n-i-1; j++)if (arr[j] > arr[j+1])swap(&arr[j], &arr[j+1]);
}

實測耗時:32.7秒
小結:實現簡單但效率最低,僅適合教學演示


2. 選擇排序

原理:每次選擇最小元素放到已排序序列末尾
時間復雜度 O ( n 2 ) O(n^2) O(n2)

#include <stdio.h>
#include <stdlib.h>
void selectionSort(int arr[], int n) {for (int i = 0; i < n-1; i++) {int min_idx = i;for (int j = i+1; j < n; j++)if (arr[j] < arr[min_idx])min_idx = j;swap(&arr[min_idx], &arr[i]);}
}

實測耗時:14.2秒
小結:比冒泡稍快但仍不適合大數據量


3. 插入排序

原理:將未排序元素插入已排序序列的合適位置
時間復雜度 O ( n 2 ) O(n^2) O(n2)

#include <stdio.h>
#include <stdlib.h>
void insertionSort(int arr[], int n) {for (int i = 1; i < n; i++) {int key = arr[i], j = i-1;while (j >= 0 && arr[j] > key) {arr[j+1] = arr[j];j--;}arr[j+1] = key;}
}

實測耗時:8.9秒
小結:在小規模或基本有序數據中表現良好


4. 希爾排序

原理:改進的插入排序,通過增量分組進行排序
時間復雜度 O ( n 1.3 ) O(n^{1.3}) O(n1.3) ~ O ( n 2 ) O(n^2) O(n2)

#include <stdio.h>
#include <stdlib.h>
void shellSort(int arr[], int n) {for (int gap = n/2; gap > 0; gap /= 2)for (int i = gap; i < n; i++)for (int j = i; j >= gap && arr[j] < arr[j-gap]; j -= gap)swap(&arr[j], &arr[j-gap]);
}

實測耗時:1.7秒
小結:突破 O ( n 2 ) O(n^2) O(n2)瓶頸,中等數據量優選


5. 歸并排序

原理:分治法典范,先分解后合并
時間復雜度 O ( n log ? n ) O(n\log n) O(nlogn)
實現要點

  • 動態分配內存用于臨時數組(malloc/free
  • 遞歸分割數組時需傳遞子數組長度
  • 合并操作直接修改原數組(通過指針傳遞)
#include <stdio.h>
#include <stdlib.h>// 合并兩個有序數組的核心函數
void merge(int arr[], int left[], int right[], int left_len, int right_len) {int i = 0, j = 0, k = 0;// 合并過程while (i < left_len && j < right_len) {if (left[i] <= right[j]) {  // 穩定性關鍵:等于時取左元素arr[k++] = left[i++];} else {arr[k++] = right[j++];}}// 處理剩余元素while (i < left_len) arr[k++] = left[i++];while (j < right_len) arr[k++] = right[j++];
}// 遞歸排序函數
void merge_sort(int arr[], int n) {if (n <= 1) return;int mid = n / 2;int *left = (int*)malloc(mid * sizeof(int));int *right = (int*)malloc((n - mid) * sizeof(int));// 分割數組for (int i = 0; i < mid; i++) left[i] = arr[i];for (int i = mid; i < n; i++) right[i - mid] = arr[i];// 遞歸排序merge_sort(left, mid);merge_sort(right, n - mid);// 合并結果merge(arr, left, right, mid, n - mid);// 釋放臨時內存free(left);free(right);
}

實測耗時:0.35秒
小結:穩定可靠的外排序首選


6. 快速排序

原理:通過基準值分區實現分治排序
時間復雜度 O ( n log ? n ) O(n\log n) O(nlogn)

#include <stdio.h>
#include <stdlib.h>
int partition(int arr[], int low, int high) {int pivot = arr[high];int i = low - 1;for (int j = low; j <= high-1; j++)if (arr[j] < pivot)swap(&arr[++i], &arr[j]);swap(&arr[i+1], &arr[high]);return i+1;
}
void quickSort(int arr[], int low, int high) {if (low < high) {int pi = partition(arr, low, high);quickSort(arr, low, pi-1);quickSort(arr, pi+1, high);}
}

實測耗時:0.12秒
小結:綜合性能最優的通用排序算法


7. 堆排序

原理:利用堆數據結構進行選擇排序
時間復雜度 O ( n log ? n ) O(n\log n) O(nlogn)

#include <stdio.h>
#include <stdlib.h>
void heapify(int arr[], int n, int i) {int largest = i, l = 2*i+1, r = 2*i+2;if (l < n && arr[l] > arr[largest]) largest = l;if (r < n && arr[r] > arr[largest]) largest = r;if (largest != i) {swap(&arr[i], &arr[largest]);heapify(arr, n, largest);}
}
void heapSort(int arr[], int n) {for (int i = n/2-1; i >= 0; i--)heapify(arr, n, i);for (int i = n-1; i > 0; i--) {swap(&arr[0], &arr[i]);heapify(arr, i, 0);}
}

實測耗時:0.28秒
小結:適合需要穩定 O ( n log ? n ) O(n\log n) O(nlogn)的場景


8. 基數排序

原理:按位數進行桶排序
時間復雜度 O ( k n ) O(kn) O(kn)
實現要點

  • 使用exp參數表示當前處理的位數(1, 10, 100…)
  • 計數排序的穩定性通過反向填充實現
  • 需手動計算最大值的位數控制循環次數
#include <stdio.h>
#include <stdlib.h>// 按指定位數進行計數排序
void counting_sort(int arr[], int n, int exp) {int output[n];int count[10] = {0};  // 十進制基數// 統計當前位出現次數for (int i = 0; i < n; i++) {int digit = (arr[i] / exp) % 10;count[digit]++;}// 計算累積頻次for (int i = 1; i < 10; i++) {count[i] += count[i - 1];}// 反向填充保證穩定性for (int i = n - 1; i >= 0; i--) {int digit = (arr[i] / exp) % 10;output[count[digit] - 1] = arr[i];count[digit]--;}// 復制回原數組for (int i = 0; i < n; i++) {arr[i] = output[i];}
}// 基數排序主函數
void radix_sort(int arr[], int n) {int max_num = arr[0];for (int i = 1; i < n; i++) {if (arr[i] > max_num) max_num = arr[i];}// 按每一位進行排序for (int exp = 1; max_num / exp > 0; exp *= 10) {counting_sort(arr, n, exp);}
}

實測耗時:0.18秒
小結:整數排序利器,但需要額外內存


二、測試公共代碼

  1. 代碼實現
    測試采用100000個隨機數進行。所有排序算法函數名不同,可以采用函數指針數組方式,通過循環實現。
// 公共代碼段
#define N 100000
int* generateArray() {int* arr = (int*)malloc(N * sizeof(int));srand(time(NULL));for(int i=0; i<N; i++) arr[i] = rand() % 1000000;return arr;
}void timeTest(void (*sort)(int*, int), int* arr) {clock_t start = clock();sort(arr, N); //用對應算法實現代函數替代,所有排序算法函數名不同,可以采用函數指針數組方式,通過循環實現printf("Time: %.2fms\n", (double)(clock()-start)*1000/CLOCKS_PER_SEC);
}
  1. 關鍵注意事項
  • 每次測試前必須復制原始數組,避免數據已排序影響測試結果
  • 基數排序默認處理非負整數,如需支持負數需修改位處理邏輯
  • 快速排序使用三數取中法優化,避免最壞情況出現
  • 歸并排序采用迭代實現,避免遞歸導致的棧溢出問題

二、綜合對比分析

算法時間復雜度空間復雜度穩定性適用場景10萬數據耗時
冒泡排序 O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)穩定教學演示32.7s
選擇排序 O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)不穩定簡單實現14.2s
插入排序 O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)穩定小規模/基本有序數據8.9s
希爾排序 O ( n 1.3 ) O(n^{1.3}) O(n1.3) O ( 1 ) O(1) O(1)不穩定中等規模數據1.7s
歸并排序 O ( n log ? n ) O(n\log n) O(nlogn) O ( n ) O(n) O(n)穩定外排序/鏈表排序0.35s
快速排序 O ( n log ? n ) O(n\log n) O(nlogn) O ( log ? n ) O(\log n) O(logn)不穩定通用排序0.12s
堆排序 O ( n log ? n ) O(n\log n) O(nlogn) O ( 1 ) O(1) O(1)不穩定實時系統/內存受限0.28s
基數排序 O ( k n ) O(kn) O(kn) O ( n + k ) O(n+k) O(n+k)穩定整數排序/固定范圍數據0.18s

工程建議

  1. 通用場景優先選擇快速排序
  2. 內存敏感時選用堆排序
  3. 穩定排序需求使用歸并排序
  4. 整數排序可嘗試基數排序
  5. 小規模數據(n<1000)使用插入排序

實際應用時需結合數據特征進行算法選擇,必要時可采用混合排序策略。

三、性能優化建議

  1. 混合排序策略:當快速排序子數組長度小于15時切換為插入排序
  2. 內存預分配:歸并排序的臨時數組可提前分配避免重復申請
  3. 基數排序優化:使用位運算替代除法操作提升計算效率
  4. 并行化改造:歸并排序和快速排序適合多線程優化

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

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

相關文章

動態規劃填表技巧:固定最后一個數 vs 固定倒數第二個數

在動態規劃中&#xff0c;填表時固定最后一個數還是倒數第二個數&#xff0c;取決于問題的定義和狀態轉移方程的設計。 目錄 1. 固定最后一個數 適用場景 特點 示例 2. 固定倒數第二個數 適用場景 特點 示例 3. 固定最后一個數與倒數第二個數的對比 4. 總結 1. 固定最…

【C】鏈式二叉樹算法題2

目錄 1 另一棵樹的子樹 1&#xff09; 題目描述 示例1&#xff1a; 示例2&#xff1a; 2&#xff09; 算法解析 3&#xff09; 代碼 2 二叉樹的遍歷 1&#xff09; 問題描述 2&#xff09; 算法解析 3&#xff09; 代碼 3 總結 1 另一棵樹的子樹 leetcode鏈接…

配置Hadoop集群

Hadoop的運行模式 本地運行&#xff1a;在一臺單機上運行&#xff0c;沒有分布式文件系統&#xff0c;直接讀寫本地操作系統的文件系統。特點&#xff1a;不對配置文件進行修改&#xff0c;Hadoop 不會啟動 偽分布式&#xff1a;也是在一臺單機上運行&#xff0c;但用不同的 …

python辦公自動化--數據可視化(pandas+matplotlib)--生成條形圖和餅狀圖

前言 前幾天我們學習了pandas讀取數據&#xff0c;還學習了如何用patplotlib繪制柱狀圖和折線圖。 今天我們繼續學習&#xff0c;如何繪制條形圖和餅狀圖。 一、課程回顧-pandas讀取數據 1.示例數據文件 這里我們用到的依舊是d盤底下的這個excel工作簿&#xff0c;這個工作簿…

基于大模型的結節性甲狀腺腫診療全流程預測與方案研究報告

目錄 一、引言 1.1 研究背景與目的 1.2 研究意義 1.3 國內外研究現狀 二、大模型預測原理與方法 2.1 相關大模型概述 2.2 數據收集與預處理 2.3 模型訓練與驗證 三、術前預測與評估 3.1 結節性質預測 3.1.1 良惡性判斷 3.1.2 與傳統診斷方法對比 3.2 手術風險預測…

不同開發語言對字符串的操作

一、字符串的訪問 Objective-C: 使用 characterAtIndex: 方法訪問字符。 NSString *str "Hello, World!"; unichar character [str characterAtIndex:0]; // 訪問第一個字符 H NSLog("%C", character); // 輸出: H NSString 內部存儲的是 UTF-16 編…

Java開發者如何接入并使用DeepSeek

目錄 一、準備工作 二、添加DeepSeek SDK依賴 三、初始化DeepSeek客戶端 四、數據上傳與查詢 五、數據處理與分析 六、實際應用案例 七、總結 【博主推薦】&#xff1a;最近發現了一個超棒的人工智能學習網站&#xff0c;內容通俗易懂&#xff0c;風格風趣幽默&#xff…

S19文件格式詳解:汽車ECU軟件升級中的核心鏡像格式

文章目錄 引言一、S19文件格式的起源與概述二、S19文件的核心結構三、S19在汽車ECU升級中的應用場景四、S19與其他格式的對比五、S19文件實例解析六、工具鏈支持與安全考量七、未來趨勢與挑戰結語引言 在汽車電子控制單元(ECU)的軟件升級過程中,S19文件(也稱為Motorola S-…

CTF雜項——[suctf 2019]簽到題

base64轉圖片 可以直接用隨波逐流 得到flag SUCTF{ffffffffT4nk}

【Python】整數除法不正確,少1的問題,以及有關浮點數轉換的精度問題

1. 問題 今天在做leetcode 不同路徑 的時候發現了個問題 對于m53 n4class Solution:def uniquePaths(self, m: int, n: int) -> int:rlt 1for i in range(0, m-1):rlt * (m n - 2 - i)for i in range(0, m-1):rlt / (i 1)return int(rlt)為什么這個結果是 26234class S…

AI無代碼平臺

以下是目前支持快速開發產品的高生產力免費AI無代碼平臺推薦&#xff0c;按功能和適用場景分類&#xff1a; 一、全棧應用開發類 Bolt.DIY DeepSeek-R1 無需編寫代碼即可開發全棧應用&#xff0c;提供免費API和無速率限制&#xff0c;支持AI編碼助手與自動化流程 。 優勢&…

Gini系數的應用 - 指標波動貢獻分析

基尼系數的定義 基尼系數是衡量數據分布不均衡程度的指標&#xff0c;取值范圍在0到1之間&#xff1a; 0 表示完全均衡&#xff08;所有值相等&#xff09;。1 表示完全不均衡&#xff08;所有值集中在一個點&#xff09;。 基尼系數的計算公式 假設有 n n n 個數據點&…

第一節: 網絡基礎與參考模型

深入理解OSI七層模型與TCP/IP四層模型:網絡工程師的入門指南 在網絡通信的世界中,OSI七層模型和TCP/IP四層模型是理解網絡架構的基礎。無論是配置路由器、排查網絡故障,還是設計復雜的網絡系統,掌握這些模型的分層結構及其功能都是必不可少的。本文將從新手角度出發,深入…

HTTP拾技雜談

HTTP拾技雜談 簡單聊聊HTTP中的那些東西 文章目錄 HTTP拾技雜談前言HTTP協議1.請求從客戶端到服務器端的4個步驟一般客戶端請求如下&#xff1a;服務端響應如下 2.Keep-AliveHTTP方法Cookie 總結 前言 超文本傳輸協議&#xff08;Hypertext Transfer Protocol &#xff0c;HT…

用Deepseek寫一個五子棋微信小程序

在當今快節奏的生活中&#xff0c;休閑小游戲成為了許多人放松心情的好選擇。五子棋作為一款經典的策略游戲&#xff0c;不僅規則簡單&#xff0c;還能鍛煉思維。最近&#xff0c;我借助 DeepSeek 的幫助&#xff0c;開發了一款五子棋微信小程序。在這篇文章中&#xff0c;我將…

自然語言處理:最大期望值算法

介紹 大家好&#xff0c;博主又來給大家分享知識了&#xff0c;今天給大家分享的內容是自然語言處理中的最大期望值算法。那么什么是最大期望值算法呢&#xff1f; 最大期望值算法&#xff0c;英文簡稱為EM算法&#xff0c;它的核心思想非常巧妙。它把求解模型參數的過程分成…

【從零開始學習計算機科學】計算機體系結構(一)計算機體系結構、指令、指令集(ISA)與量化評估

【從零開始學習計算機科學】計算機體系結構(一)計算機體系結構、指令、指令集(ISA)與量化評估 概論計算機體系結構簡介計算機的分類并行體系結構指令集體系結構(ISA)分類存儲器尋址尋址模式操作數大小指令ISA的編碼程序的優化計算機體系結構量化評估存儲器體系結構概論 …

Electron使用WebAssembly實現CRC-32 常用標準校驗

Electron使用WebAssembly實現CRC-32 常用標準校驗 將C/C語言代碼&#xff0c;經由WebAssembly編譯為庫函數&#xff0c;可以在JS語言環境進行調用。這里介紹在Electron工具環境使用WebAssembly調用CRC-32 常用標準格式校驗的方式。 CRC-32 常用標準校驗函數WebAssembly源文件…

Docker基礎篇——Ubuntu下Docker安裝

大家好我是木木&#xff0c;在當今快速發展的云計算與云原生時代&#xff0c;容器化技術蓬勃興起&#xff0c;Docker 作為實現容器化的主流工具之一&#xff0c;為開發者和運維人員帶來了極大的便捷 。下面我們一起進行Docker安裝。 Docker的官方Ubuntu安裝文檔&#xff0c;如…

第五課:Express框架與RESTful API設計:技術實踐與探索

在使用Node.js進行企業應用開發&#xff0c;常用的開發框架Express&#xff0c;其中的中間件、路由配置與參數解析、RESTful API核心技術尤為重要&#xff0c;本文將深入探討它們在應用開發中的具體使用方法&#xff0c;最后通過Postman來對開發的接口進行測試。 一、Express中…