NO.55十六屆藍橋杯備戰|排序|插入|選擇|冒泡|堆|快速|歸并(C++)

插?排序

插?排序(Insertion Sort)類似于玩撲克牌插牌過程,每次將?個待排序的元素按照其關鍵字??插?到前?已排好序的序列中,按照該種?式將所有元素全部插?完成即可

#include <iostream>  
using namespace std;  const int N = 1e5 + 10;  
int n;  
int a[N];  void insert_sort()  
{  // 依次枚舉待排序的元素  for(int i = 2; i <= n; i++) // 第?個位置默認就是有序的  {  int key = a[i];  // 前?? key ?的,統?右移  int j = i - 1;  while(j >= 1 && a[j] > key)  {  a[j + 1] = a[j];  j--;  }  a[j + 1] = key;  }  
}int main()  
{  cin >> n;  for(int i = 1; i <= n; i++) cin >> a[i];  insert_sort();  for(int i = 1; i <= n; i++) cout << a[i] << " ";  return 0;  
}

時間復雜度

  • 當整個序列有序的時候,插?排序最優,此時時間復雜度為O(n) 。
  • 當整個序列逆序的時候,每個元素都要跑到最前?,時間復雜度為O(n2)

選擇排序

選擇排序(Selection Sort)是?種特別直觀的排序算法。每次找出未排序序列中最?的元素,然后放進有序序列的后?

#include <iostream>  
using namespace std;  
const int N = 1e5 + 10;  
int n;  
int a[N];  
void selection_sort()  
{  for(int i = 1; i < n; i++) // 待排序區間的?位置  {  // [i, n] 區間就是待排序的區間  int pos = i;for(int j = i + 1; j <= n; j++) // 查找待排序區間最?的元素的下標  {  if(a[j] < a[pos])  {  pos = j;  }  }  swap(a[i], a[pos]);  }  
}  
int main()  
{  cin >> n;  for(int i = 1; i <= n; i++) cin >> a[i];  selection_sort();  for(int i = 1; i <= n; i++) cout << a[i] << " ";  return 0;  
}

【時間復雜度】

  • ?論數組有序還是?序,在未排序區間內找最?值的時候,都需要遍歷?遍待排序的區間,因此時間復雜度為O(n2)

冒泡排序

冒泡排序(Bubble Sort)也是?種簡單的排序算法。它的?作原理是每次檢查相鄰兩個元素,如果前?的元素與后?的元素滿?給定的排序條件,就將相鄰兩個元素交換。當沒有相鄰的元素需要交換時,排序就完成了。
由于在算法的執?過程中,較?的元素像是?泡般慢慢浮到數列的末端,故叫做冒泡排序

#include <iostream>
using namespace std;  
const int N = 1e5 + 10;  
int n;  
int a[N];  
// 優化后的冒泡排序  
void bubble_sort()  
{  // 依次枚舉待排序區間的最后?個元素  for(int i = n; i > 1; i--)  {  bool flag = false;  // [1, i] 就是待排序區間  for(int j = 1; j < i; j++)  {  if(a[j] > a[j + 1])  {  swap(a[j], a[j + 1]);  flag = true;  }  }  if(flag == false) return;  }  
}  
int main()  
{  cin >> n;  for(int i = 1; i <= n; i++) cin >> a[i];  bubble_sort();  for(int i = 1; i <= n; i++) cout << a[i] << " ";  return 0;  
}

時間復雜度

  • 如果數組有序,只會掃描?遍,時間復雜度為O(n) 。
  • 如果逆序,所有元素都會向后冒?次到合適位置,時間復雜度為O(n2)

堆排序

堆排序(Heap Sort)是指利?堆這種數據結構所設計的?種排序算法。本質上是優化了選擇排序算法,如果將數據放在堆中,能夠快速找到待排序元素中的最?值或最?值。
堆排序的過程分兩步:

  1. 建堆。升序建?堆,降序建?堆。
    建堆過程,從倒數第?個?葉?節點開始,倒著?直到根結點位置,每個結點進?向下調整。
  2. 排序。刪除堆頂的邏輯。
    每次將堆頂元素與堆中最后?個元素交換,然后將堆頂元素往下調整。直到堆中剩余?個元素,所有元素就都有序了。
    因此,堆排序僅需?到向下調整算法
#include <iostream>  
using namespace std;  
const int N = 1e5 + 10;  
int n;  
int a[N];  
void down(int parent, int len)  
{  int child = parent * 2;  while(child <= len)  {  if(child + 1 <= len && a[child + 1] > a[child]) child++;  if(a[parent] >= a[child]) return;swap(a[parent], a[child]);  parent = child;  child = parent * 2;  }  
}  
void heap_sort()  
{  // 1. 建堆  for(int i = n / 2; i >= 1; i--)  {  down(i, n);  }  // 2. 排序  for(int i = n; i > 1; i--) // 枚舉堆??最后?個元素的位置  {  swap(a[1], a[i]);  down(1, i - 1);  }  
}  
int main()  
{  cin >> n;  for(int i = 1; i <= n; i++) cin >> a[i];  heap_sort();  for(int i = 1; i <= n; i++) cout << a[i] << " ";  return 0;  
}

時間復雜度
時間復雜度需要計算兩部分:?部分是建堆的時間復雜度,另?部分是排序。

  • 排序部分的時間復雜度很好估計,每次都是從堆中選擇?個最?值,然后與最后?個元素交換,然后調整。?次選擇的時間復雜度為log n ,?共執?n 次,?概就是n log n 級別。
  • 建堆的時間復雜度:
    計算向下調整算法建堆時間復雜度
    ![[Pasted image 20250322161630.png]]

則需要移動結點總的移動步數為:每層結點個數*向下調整次數
T ( h ) = 2 h ? 1 ? h T(h) = 2^h-1-h T(h)=2h?1?h
根據?叉樹的性質:n = 2^h - 1 和h = log2 (n + 1)
T ( n ) = n ? log ? 2 ( n + 1 ) ≈ n T(n) = n - \log_{2}(n+1) \approx n T(n)=n?log2?(n+1)n

綜上所述,堆排序的時間復雜度主要取決于排序的過程,也就是n log n

快速排序

快速排序(Quick Sort),既然敢起這樣的名字,說明它是常?排序算法中較為優秀的。事實上,在很多情況下,快排確實是效率較?的算法

算法原理

常規快排:在待排序區間中任取?個元素作為樞軸(pivot,或稱基準值,通常選取區間?元素),然后按照基準值??將區間中元素分割成左右兩部分,左側區間中元素?于基準值,右側區間中元素?于等于基準值,即基準值已經放在其該放的位置上,該過程稱為?次劃分。劃分結束后,再遞歸排基準值左側,遞歸排基準值右側即可
![[Pasted image 20250322163740.png]]

優化?:三路劃分

三路劃分優化:其實可以做到按照基準元素,將所有元素分成三個區間。左部分全部?于pivot,中間部分全部等于pivot,右部分全部?于pivot。然后中間部分就不?管了,直接遞歸處理左右部分

  1. 從區間中任取一個元素作為基準值,一般取區間最左側元素,然后按照基準值對區間中元素進行劃分
    ![[Pasted image 20250322164110.png]]

  2. 遞歸排基準值左側;遞歸排基準值右側
    ?這個三路劃分,就是典型的數組分三塊算法

優化?:隨機選擇基準元素

選擇基準元素的?式:

  • 每次選擇待排序序列的最左邊元素
    那么,當整個序列有序的時候,每次遞歸就會劃分出特別?的?段右區間,遞歸的層數是n次,每次要遍歷整個數組?遍,時間復雜度就退化成n^2 。
    每次選擇最右邊元素也是同理。
  • 每次選擇待排序序列的中間元素
    可以構造?個特殊的序列,使得每次取中間元素的時候都會取到最?值,依舊會退化成n^2。
  • 隨機選擇基準元素
    每次選擇基準元素的時候,都從待排序的序列中隨機選擇?個數。在隨機性的前提下,可以證明算法的時間復雜度趨近于nlogn 。
    因此,每次選擇基準元素時,都使?隨機函數選擇
C++中的隨機函數

C++提供了函數srand和rand,搭配使?可以返回?個隨機值

#include <iostream>  
#include <ctime>  
using namespace std;  
int main()  
{  srand(time(0)); // 種下?個隨機數種?  for(int i = 1; i <= 10; i++)  {  cout << rand() << endl; // 每次?成?個隨機值  }  return 0;  
}

![[Pasted image 20250322171920.png]]

left和right指向第一個和最后一個元素,假設p等于4
![[Pasted image 20250322172121.png]]

i從第一個元素往最后一個元素遍歷
現在ai是4,和p一樣大,i++
![[Pasted image 20250322180638.png]]

ai是2,比p小,交換到前面,++l和i交換,i++
![[Pasted image 20250322180758.png]]

現在ai是4,和p一樣大,i++
![[Pasted image 20250322180822.png]]

現在ai是5,比p大,交換到最右邊,i和–r交換
![[Pasted image 20250322180911.png]]

i這是下標為4,ai為1,比p小,++l和i交換,i++
![[Pasted image 20250322181036.png]]

這是i等于5,r也是5,遍歷結束,此時p=4,兩個4已經在正確的位置上
中間區域也就是相等的區域,是l+1到r-1
左邊比p小的區域是left到l,右邊比p大的區域是r到right
接著遍歷left到l和r到right

#include <iostream>  
#include <ctime>  
using namespace std;  
const int N = 1e5 + 10;  
int n;  
int a[N];  
// 優化?:隨機選擇基準元素  
int get_random(int left, int right)  
{  return a[rand() % (right - left + 1) + left];  
}  void quick_sort(int left, int right)  
{  if(left >= right) return;  // 1. 選擇?個基準元素  int p = get_random(left, right);  // 2. 數組分三塊 - 荷蘭國旗問題  int l = left - 1, i = left, r = right + 1;  while(i < r)  {  if(a[i] < p) swap(a[++l], a[i++]);  else if(a[i] == p) i++;  else swap(a[--r], a[i]);  }  // [left, l] [l + 1, r - 1] [r, right]  quick_sort(left, l);  quick_sort(r, right);  
}  
int main()  
{  srand(time(0));  cin >> n;  for(int i = 1; i <= n; i++) cin >> a[i];  quick_sort(1, n);for(int i = 1; i <= n; i++) cout << a[i] << " ";  return 0;  
}

時間復雜度

  • 如果每次基準元素都選擇得當,數組劃分的比較均勻,時間復雜度=遞歸層數*N*logN
  • 如果劃分不當,數組分布比較極端,時間復雜度退化成N^2

歸并排序

歸并排序(Merge Sort)是?論數據有什么特性,時間復雜度就能穩定O(n log n) 的排序算法
歸并排序?的是分治思想,不知道分治是啥也沒關系,后續算法課會講到。它的主要過程分兩步:

  1. 將整個區間從中間?分為?,先把左邊和右邊排排序;
  2. 然后將左右兩個有序的區間合并在?起。
    其中,如何讓左右兩邊有序,就繼續交給歸并排序,因此歸并排序是?遞歸來實現的;合并兩個有序區間的操作,在順序表中講過類似的算法題
#include <iostream>  
using namespace std;  
const int N = 1e5 + 10;  
int n;  
int a[N];  
int tmp[N]; // 輔助歸并排序時,合并兩個有序數組  
void merge_sort(int left, int right)  
{  if(left >= right) return;  // 1. 先?分為?  int mid = (left + right) >> 1;  // [left, mid] [mid + 1, right]  // 2. 先讓左右區間有序  merge_sort(left, mid);  merge_sort(mid + 1, right);// 3. 合并兩個有序數組  int cur1 = left, cur2 = mid + 1, i = left;  // [left, mid] [mid + 1, right]  while(cur1 <= mid && cur2 <= right)  {  if(a[cur1] <= a[cur2]) tmp[i++] = a[cur1++];  else tmp[i++] = a[cur2++];  }  while(cur1 <= mid) tmp[i++] = a[cur1++];  while(cur2 <= right) tmp[i++] = a[cur2++];  for(int j = left; j <= right; j++)  {  a[j] = tmp[j];  }  
}  int main()  
{  cin >> n;  for(int i = 1; i <= n; i++) cin >> a[i];  merge_sort(1, n);  for(int i = 1; i <= n; i++) cout << a[i] << " ";  return 0;  
}

【時間復雜度】
每次遞歸都是標準的?分為?,因此時間復雜度為O(n log n)

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

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

相關文章

【Oracle資源損壞類故障】:詳細了解壞塊

目錄 1、物理壞塊與邏輯壞塊 1.1、物理壞塊 1.2、邏輯壞塊 2、兩個壞塊相關的參數 2.1、db_block_checksum 2.2、db_block_checking 3、檢測壞塊 3.1、告警日志 3.2、RMAN 3.3、ANALYZE 3.4、數據字典 3.5、DBVERIFY 4、修復壞塊 4.1、RMAN修復 4.2、DBMS_REPA…

計算機網絡高頻(二)TCP/IP基礎

計算機網絡高頻(二)TCP/IP基礎 1.什么是TCP/IP?? TCP/IP是一種網絡通信協議,它是互聯網中最常用的協議之一。TCP/IP有兩個基本的協議:TCP(傳輸控制協議)和IP(互聯網協議)。 TCP(Transmission Control Protocol,傳輸控制協議)是一種可靠的、面向連接的協議。它負…

【大模型算法工程】大模型應用工具化、忠誠度以及知識庫場景下PDF雙欄解析問題的討論

1. 大模型時代應用工具化以及無忠誠度現象討論 接觸大模型久了&#xff0c;也慢慢探到一些大模型能力表現非常自然和突出的場景&#xff0c;比如AI搜索&#xff08;依賴大模型的理解總結能力&#xff09;、AI對話&#xff08;即chat&#xff0c;依賴大模型的生成能力&#xff0…

Java EE(13)——網絡編程——UDP/TCP回顯服務器

前言 本文主要介紹UDP和TCP相關的API&#xff0c;并且基于這兩套API實現回顯服務器 UDP和TCP UDP和TCP屬于網絡五層模型中傳輸層的協議 特點&#xff1a; UDP&#xff1a;無連接&#xff0c;不可靠&#xff0c;面向數據包&#xff0c;全雙工 TCP&#xff1a;有連接&#xff…

【藍橋杯】12111暖氣冰場(多源BFS 或者 二分)

思路 這題可以用BFS做&#xff0c;也可以用二分來做。 用二分這里只提供一個思路&#xff1a;對時間來二分查找&#xff0c;check函數就是檢查在特定的時間 t 0 t_0 t0?內每一個暖氣爐的傳播距離能否覆蓋所有格子。 用BFS做&#xff1a; 由幾個點開始向外擴散&#xff0c;知道…

使用bat批量獲取WORD中包含對應字符的段落,段落使用回車換行

get_word_paragraphs.vbs 獲取命令行參數 If WScript.Arguments.Count 0 ThenWScript.Quit 1 End If 獲取 Word 文檔路徑 docPath WScript.Arguments(0) 創建 Word 應用程序對象 Set objWord CreateObject("Word.Application") objWord.Visible False 打開 Word …

DeepSeek自學手冊:《從理論(模型訓練)到實踐(模型應用)》|73頁|附PPT下載方法

導 讀INTRODUCTION 今天分享是由ai呀蔡蔡團隊帶來的DeepSeek自學手冊&#xff1a;《從理論&#xff08;模型訓練&#xff09;到實踐&#xff08;模型應用&#xff09;》&#xff0c;這是一篇關于DeepSeek模型訓練、應用場景及替代方案的綜合指南文章&#xff0c;主要介紹了Deep…

WEB API 設計規范

REST API 簡介 REST 是 Representational State Transfer 的縮寫&#xff0c;它將資源作為核心概念&#xff0c;通過 HTTP 方法對資源進行操作。其本身是一套圍繞資源進行操作的架構規范。在實際應用中&#xff0c;更多的是體現在 API 的設計上。 企業在進行產品設計開發時&a…

QT軟件匠心開發,塑造卓越設計服務

在當今這個數字化飛速發展的時代&#xff0c;軟件已經成為我們生活中不可或缺的一部分。而QT&#xff0c;作為一款跨平臺的C圖形用戶界面應用程序開發框架&#xff0c;憑借其強大的功能和靈活性&#xff0c;在眾多軟件開發工具中脫穎而出。我們深知&#xff0c;在軟件開發領域&…

標貝科技入選2025年市級數據要素市場化配置改革“揭榜掛帥”名單

近日&#xff0c;山東省大數據局、青島市大數據局公布2025年數據要素市場化配置改革“揭榜掛帥”名單。標貝科技聯合嶗山區電子政務和大數據中心申報的“政務熱線通話錄音數據價值挖掘與權益保護”項目成功入選。這一成果不僅彰顯了標貝科技在數據領域的創新實力&#xff0c;更…

Flutter TextField 從入門到精通:掌握輸入框的完整指南

目錄 1. 引言 2. TextField 的基本用法 3. 主要屬性 4. 自定義 TextField 樣式 4.1 自定義邊框與提示文本 4.2 增加前綴/后綴圖標 4.3 只允許輸入數字 4.4 表單驗證系統 4.5 動態樣式修改 4.6 防抖搜索&#xff08;Debounce&#xff09; 5. 結論 相關推薦 1. 引言…

藍橋杯備賽 背包問題

背包問題 ![[背包問題.png]] 01背包 1.題意概要&#xff1a;有 n n n個物品和一個容量為 V V V的背包&#xff0c;每個物品有重量 w i w_i wi?和價值 v i v_i vi? 兩種屬性&#xff0c;要求選若干物品放入背包使背包中物品的總價值最大且背包中物品的總重量不超過背包的容…

MyBatis-Plus 自動填充:優雅實現創建/更新時間自動更新!

目錄 一、什么是 MyBatis-Plus 自動填充&#xff1f; &#x1f914;二、自動填充的原理 ??三、實際例子&#xff1a;創建時間和更新時間字段自動填充 ?四、注意事項 ??五、總結 &#x1f389; &#x1f31f;我的其他文章也講解的比較有趣&#x1f601;&#xff0c;如果喜歡…

arduino R4 SD卡讀寫測試

使用買來的 st7789LCD 顯示器背面就帶著一個 tf 卡槽&#xff0c;可以直接連接 tf 卡。使用 Sdfat 庫就可以實現對 sd 卡的讀寫操作。這里嘗試測試 sd 卡的讀寫功能。 LCD 顯示器的初始化 //定義LCD的對象 Adafruit_ST7789 tft Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);tf…

【武漢·4月11日】Parasoft聯合光庭信息研討會|邀您共探AI賦能新機遇

Parasoft聯合光庭信息Workshop邀您共探AI賦能新機遇 AI浪潮已至&#xff0c;你準備好了嗎&#xff1f; 在智能網聯汽車飛速發展的今天&#xff0c;AI技術正以前所未有的速度重塑行業生態。如何把握AI機遇&#xff0c;賦能企業創新&#xff1f; 4月11日&#xff0c;自動化軟件…

VLLM專題(三十九)—自動前綴緩存(二)

前綴緩存(Prefix Caching)是一種在LLM推理中廣泛使用的優化技術,旨在避免冗余的提示詞(prompt)計算。其核心思想很簡單——我們緩存已處理請求的鍵值緩存(kv-cache)塊,并在新請求的前綴與之前請求相同時重用這些塊。由于前綴緩存幾乎是一種“免費的午餐”,并且不會改變…

自動駕駛系統的車輛動力學建模:自行車模型與汽車模型的對比分析

在自動駕駛系統的車輛動力學建模中&#xff0c;自行車模型&#xff08;Bicycle Model&#xff09;和更復雜的汽車模型&#xff08;如雙軌模型或多體動力學模型&#xff09;各有其適用場景和優缺點。以下是兩者的詳細對比及選擇原因解析&#xff1a; 1. 模型定義與核心差異 特性…

C語言入門教程100講(6)類型修飾符

文章目錄 1. 什么是類型修飾符&#xff1f;2. 常見的類型修飾符3. 類型修飾符的使用3.1 short 和 long3.2 signed 和 unsigned 4. 類型修飾符的組合5. 示例代碼代碼解析&#xff1a;輸出結果&#xff1a; 6. 常見問題問題 1&#xff1a;short 和 long 的具體大小是多少&#xf…

Linux-Ubuntu 系統學習筆記 | 從入門到實戰

&#x1f4d8; Linux-Ubuntu 系統學習筆記 | 從入門到實戰 &#x1f4dc; 目錄 環境安裝基本操作Linux操作系統介紹文件系統常用命令用戶權限管理編輯器vimGCC編譯器動態庫與靜態庫Makefile 1. 環境安裝 &#x1f31f; 下載鏡像 推薦使用清華大學開源鏡像站下載Ubuntu鏡像&a…

防火墻帶寬管理

拓撲 配置 [fw]interface GigabitEthernet 0/0/0 [fw-GigabitEthernet0/0/0]service-manage all permit [fw]interface GigabitEthernet 1/0/0 [fw-GigabitEthernet1/0/0]ip address 12.0.0.1 24 [fw]interface GigabitEthernet 1/0/1 [fw-GigabitEthernet1/0/1]ip ad…