排序---選擇排序(Selection Sort)

一、選擇排序的基本概念

選擇排序(Selection Sort)是一種簡單直觀的排序算法,其核心思想是每次從待排序元素中找到最值(最小值或最大值),將其放到已排序序列的末尾,重復此過程直到所有元素完成排序

與冒泡排序通過相鄰元素交換逐步"浮"出最值不同,選擇排序通過"選擇"最值并一次性交換到目標位置,減少了交換操作的次數。這種特性使選擇排序在某些場景下(如交換成本較高的情況)表現優于冒泡排序。

二、選擇排序的工作原理

選擇排序的工作過程可分為以下步驟,我們以升序排序(找最小值)為例說明:

  1. 劃分區域:將數組分為"已排序區域"和"未排序區域"。初始狀態下,已排序區域為空,未排序區域為整個數組。
  2. 查找最值:在未排序區域中找到最小元素,記錄其索引。
  3. 交換元素:將找到的最小元素與未排序區域的第一個元素交換,此時該元素被納入已排序區域。
  4. 重復迭代:縮小未排序區域的范圍(左邊界右移一位),重復步驟2和3,直到未排序區域為空。

示例演示
對數組 [64, 25, 12, 22, 11] 進行升序排序的過程:

  • 第1輪:未排序區域為 [64, 25, 12, 22, 11],最小值為11(索引4),與未排序區域第一個元素64交換 → 數組變為 [11, 25, 12, 22, 64](已排序區域:[11])。
  • 第2輪:未排序區域為 [25, 12, 22, 64],最小值為12(索引2),與25交換 → 數組變為 [11, 12, 25, 22, 64](已排序區域:[11, 12])。
  • 第3輪:未排序區域為 [25, 22, 64],最小值為22(索引3),與25交換 → 數組變為 [11, 12, 22, 25, 64](已排序區域:[11, 12, 22])。
  • 第4輪:未排序區域為 [25, 64],最小值為25(索引3),無需交換 → 數組保持 [11, 12, 22, 25, 64](已排序區域:[11, 12, 22, 25])。
  • 結束:未排序區域僅剩最后一個元素64,排序完成。
三、算法特性分析
  1. 時間復雜度
    選擇排序的時間復雜度不受輸入數據的影響,始終為 O(n2)

    • 外層循環需要執行 n-1 次(每次確定一個元素的位置)。
    • 內層循環在第 i 輪需要遍歷 n-i 個元素(尋找未排序區域的最值)。
    • 總操作次數為 (n-1) + (n-2) + ... + 1 = n(n-1)/2,近似為 n2/2,因此時間復雜度為 O(n2)。
  2. 空間復雜度
    選擇排序僅使用常數級別的額外空間(如存儲最值索引和臨時交換變量),因此空間復雜度為 O(1),是一種"原地排序"算法。

  3. 穩定性
    選擇排序是不穩定的排序算法。例如,對數組 [2, 2, 1] 排序時,第一個2會與1交換,導致兩個2的相對位置發生改變(原順序為 [2?, 2?, 1],排序后為 [1, 2?, 2?])。

  4. 優缺點

    • 優點:實現簡單,空間復雜度低,交換操作次數少(最多 n-1 次)。
    • 缺點:時間復雜度高,不適合處理大規模數據;穩定性差,不適用于要求保持相等元素相對順序的場景。
四、C/C++代碼實現

下面是選擇排序的C++實現,包含完整的排序函數、測試用例和打印函數:

#include <iostream>
#include <vector>using namespace std;// 選擇排序函數(升序)
void selectionSort(int arr[], int n) {// 外層循環:控制已排序區域的邊界(0 ~ i-1為已排序)for (int i = 0; i < n - 1; i++) {int minIndex = i; // 記錄未排序區域中最小值的索引,初始假設為i// 內層循環:在未排序區域(i ~ n-1)中尋找最小值for (int j = i + 1; j < n; j++) {if (arr[j] < arr[minIndex]) {minIndex = j; // 更新最小值索引}}// 將找到的最小值與未排序區域的第一個元素(arr[i])交換if (minIndex != i) { // 若最小值就是當前元素,無需交換int temp = arr[i];arr[i] = arr[minIndex];arr[minIndex] = temp;}}
}// 打印數組元素
void printArray(int arr[], int n) {for (int i = 0; i < n; i++) {cout << arr[i] << " ";}cout << endl;
}int main() {// 測試用例1:整數數組int arr1[] = {64, 25, 12, 22, 11};int n1 = sizeof(arr1) / sizeof(arr1[0]);cout << "排序前的數組:";printArray(arr1, n1);selectionSort(arr1, n1);cout << "排序后的數組:";printArray(arr1, n1);// 測試用例2:包含重復元素的數組int arr2[] = {3, 1, 4, 1, 5, 9, 2, 6};int n2 = sizeof(arr2) / sizeof(arr2[0]);cout << "\n排序前的數組(含重復元素):";printArray(arr2, n2);selectionSort(arr2, n2);cout << "排序后的數組(含重復元素):";printArray(arr2, n2);return 0;
}
五、代碼解析
  1. 排序函數 selectionSort

    • 外層循環變量 i 表示已排序區域的邊界(0 ~ i-1 為已排序元素),循環范圍為 0 ~ n-2(最后一個元素無需排序)。
    • 內層循環從 i+1 開始遍歷未排序區域,通過 minIndex 記錄最小值的位置。
    • 找到最小值后,若其位置與 i 不同,則交換 arr[i]arr[minIndex],將最小值放入已排序區域的末尾。
  2. 輔助函數 printArray
    用于打印數組元素,方便觀察排序前后的變化。

  3. 測試用例

    • 第一個測試用例驗證基本排序功能,第二個測試用例驗證對含重復元素數組的排序效果(可觀察到選擇排序的不穩定性)。
六、優化方向

標準選擇排序可通過以下方式優化:

  1. 雙向選擇排序
    每次迭代同時尋找未排序區域的最小值和最大值,分別放到已排序區域的兩端,減少循環次數(迭代次數從 n-1 減少到 n/2)。

    void bidirectionalSelectionSort(int arr[], int n) {int left = 0, right = n - 1;while (left < right) {int minIndex = left, maxIndex = right;// 找最小值和最大值for (int i = left; i <= right; i++) {if (arr[i] < arr[minIndex]) minIndex = i;if (arr[i] > arr[maxIndex]) maxIndex = i;}// 交換最小值到左側swap(arr[left], arr[minIndex]);// 若最大值在左側(被交換過),更新maxIndexif (maxIndex == left) maxIndex = minIndex;// 交換最大值到右側swap(arr[right], arr[maxIndex]);left++;right--;}
    }
    
  2. 優化交換操作
    對于大型元素(如結構體),交換操作成本較高,可先記錄最值位置,最后一次性移動元素(減少復制次數)。

七、適用場景

選擇排序適合以下場景:

  • 數據量較小(如 n < 100),對排序效率要求不高。
  • 內存空間有限,需要原地排序(空間復雜度O(1))。
  • 交換操作成本較高(選擇排序的交換次數最少)。

對于大規模數據(n > 1000),建議使用快速排序、歸并排序等O(n log n)級別的算法。


選擇排序是一種基礎的排序算法,其核心思想是"選擇最值并交換",實現簡單但效率較低。
在實際開發中,需根據數據規模、空間限制和穩定性要求,選擇合適的排序算法。

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

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

相關文章

前端菜單權限方案

方案一&#xff1a;前端全量配置路由表 后端返回權限碼思路所有可能的路由都在前端 router 中靜態配置好&#xff08;就像你現在這樣&#xff09;。登錄后&#xff0c;后端返回當前用戶的菜單權限&#xff08;通常是一個權限 code 列表&#xff09;。前端根據權限碼過濾掉無權…

spring項目部署后為什么會生成 logback-spring.xml文件

以下內容為豆包生成&#xff0c;此處僅做記錄在 Spring 項目&#xff08;尤其是 Spring Boot 項目&#xff09;部署后生成 logback-spring.xml 文件&#xff0c;通常有以下幾種原因&#xff1a;1. 項目打包時主動包含了該文件logback-spring.xml 是 Logback 日志框架在 Spring …

如何解決pip安裝報錯ModuleNotFoundError: No module named ‘vaex’問題

【Python系列Bug修復PyCharm控制臺pip install報錯】如何解決pip安裝報錯ModuleNotFoundError: No module named ‘vaex’問題 摘要 在Python開發過程中&#xff0c;使用pip install時遇到錯誤是非常常見的情況。特別是在使用PyCharm等集成開發環境&#xff08;IDE&#xff0…

實習總結——關于聯調解決的因CRC校驗導致協議交互失敗的調試經驗總結

1.場景還原&#xff1a;在我開發USB PD測試模塊時&#xff0c;發現待測主板始終不回復Request消息&#xff0c;導致我的測試失敗&#xff1b;此時我的任務就是快速定位這個協議交互失敗的原因&#xff0c;無論是軟件、硬件還是協同。2.大致的調試步驟&#xff1a;1.首先使用了邏…

STM32之RTC

RTC簡介 實時時鐘(Real Time Clock&#xff0c;RTC)&#xff0c;本質是一個計數器&#xff0c;計數頻率常為秒&#xff0c;專門用來記錄時間。 普通定時器拿來作時鐘可行嗎&#xff1f;普通定時器無法掉電運行&#xff01; RTC特性&#xff1a; 1&#xff0c;能提供時間&…

【OC】單例模式

文章目錄前言概念優缺點優點缺點兩種使用模式懶漢模式實現代碼運行結果餓漢模式實現代碼運行結果在自定義類方法時的幾種常見寫法總結前言 在之前我們已經學習過單例模式的有關內容&#xff0c;但是只是最簡單的單例&#xff0c;無法勝任多線程或者稍微多一點的情況便無法確定…

機器學習(七)決策樹-分類

一 概念1 決策節點通過條件判斷而進行分支選擇的節點。將樣本的屬性值&#xff0c;也就是特征值與決策節點上的值進行比較&#xff0c;從而判斷它的流向。2 葉子節點沒有子節點的節點&#xff0c;表示最終的決策結果。3 決策樹的深度所有節點的最大層次數決策樹具有一定的層次結…

IT 服務管理的新格局:從工單系統到一體化 ITSM 平臺

企業 IT 部門的角色轉變在過去&#xff0c;IT 部門更多被視為“技術支持”&#xff0c;主要負責設備維護和故障處理。但隨著數字化轉型加速&#xff0c;IT 已經成為業務連續性和創新的重要推動力。從客戶體驗到數據安全&#xff0c;從業務敏捷到成本控制&#xff0c;IT 服務管理…

創建一個Spring Boot Starter風格的Basic認證SDK

文章目錄前言設計思路SDK實現步驟1. 創建SDK Maven項目&#xff08;sdk目錄&#xff09;2. 實現配置類3. 實現認證邏輯4. 實現攔截器5. 實現自動配置6. 創建spring.factories文件使用方集成步驟1. 引入SDK依賴2. 配置Application屬性3. 創建測試接口4. 測試接口訪問SDK擴展功能…

mybatis處理統計sql進度丟失問題

如何處理統計sql進度丟失 SELECT sum(decimal_column) AS sum_value FROM your_table如上sql執行時沒有問題&#xff0c;在數據庫可視工具可以正常顯示&#xff0c;但是在mybatis執行時&#xff0c;卻出現解決辦法 使用轉 decimal 控制精度 SELECT CAST(SUM(decimal_column) A…

全球首款!科聰控制器獲德國 TüV 萊茵功能安全認證

近日&#xff0c;浙江科聰控制技術有限公司&#xff08;以下簡稱"科聰"&#xff09;的安全移動機器人控制器MSC5000榮獲全球權威認證機構德國萊茵TV集團&#xff08;TV Rheinland&#xff09;頒發的功能安全認證證書。這款控制器是全球首款通過SIL3、PLe 認證的移動機…

pureadmin的動態路由和靜態路由

在 PureAdmin&#xff08;基于 Vue3 的后臺管理框架&#xff09;中&#xff0c;靜態路由和動態路由是實現路由管理的兩種方式&#xff0c;主要區別在于路由的定義時機、加載方式和靈活性&#xff0c;具體區別如下&#xff1a; 1. 靜態路由 定義方式&#xff1a;路由規則在代碼中…

第3章:CPU實戰

1. Linux操作系統CPU平均負載 以前我們總認為CPU使用率和CPU平均負載是一樣的&#xff0c;負載高了就是CPU使用率提高。但是到底是什么情況呢&#xff1f; 1.1. CPU的平均負載 單位時間內 系統處于 可運行狀態 和不可中斷狀態 的平均進程數&#xff0c;就是平均活躍進程數&a…

【Vue3】06-利用setup編寫vue(1)

其它篇章&#xff1a; 1.【Vue3】01-創建Vue3工程 2.【Vue3】02-Vue3工程目錄分析 3.【Vue3】03-編寫app組件——src 4.【Vue3】04-編寫vue實現一個簡單效果 5.【Vue3】05-Options API和Composition API的區別 6.【Vue3】06-利用setup編寫vue&#xff08;1&#xff09; 7.【Vue…

UDS NRC速查

目錄 NRC 一、通用NRC(0x10~0x5F) 二、數據相關NRC(0x70~0x8F) 三、會話與狀態NRC 注意事項 UDS中的NRC(Negative Response Code)即否定響應碼,用于在診斷通信中表示服務端無法成功執行客戶端請求的原因。以下是一些常用的UDS NRC碼及其含義: HEX Name Description 01 …

【AI論文】多模態大型語言模型的視覺表征對齊

摘要&#xff1a;通過視覺指令微調訓練的多模態大型語言模型&#xff08;MLLMs&#xff09;在各類任務中均取得了優異表現&#xff0c;然而在以視覺為中心的任務&#xff08;如物體計數或空間推理&#xff09;中&#xff0c;其性能仍存在局限。我們將這一差距歸因于當前主流的純…

SKywalking Agent配置+Oracle監控插件安裝指南

SKywalking Agent配置Oracle監控插件安裝指南前言&#xff1a; SkyWalking Elasticsearch8 容器化部署指南 Skywalking版本&#xff1a;V10.2.0 Skywalking Agent版本&#xff1a;V9.4.0 Skywalking Agent下載地址&#xff1a;Downloads | Apache SkyWalking 插件下載地址&…

ES相關問題匯總

問題一&#xff1a;關于【QueryBuilder對象】和【Query String語法】查詢時底層運行方式和結果的差異

5. STM32 時鐘系統分配

文章目錄下述將以stm32f407 為例1. 時鐘系統及頻率分析2. 時鐘配置下述將以stm32f407 為例 1. 時鐘系統及頻率分析 上述STM32F4時鐘系統圖解析入下&#xff1a; STM32F407 系列微控制器&#xff08;基于 Cortex-M4 內核&#xff0c;帶 FPU&#xff09;的工作頻率配置如下&…

《從 0 建立測試開發認知:先搞懂 “是什么”,再學 “怎么做”》

&#x1f525;個人主頁&#xff1a;草莓熊Lotso &#x1f3ac;作者簡介&#xff1a;C研發方向學習者 &#x1f4d6;個人專欄&#xff1a; 《C知識分享》《Linux 入門到實踐&#xff1a;零基礎也能懂》《數據結構與算法》《測試開發實戰指南》《算法題闖關指南》 ??人生格言&a…