[C語言]常見排序算法①

1.排序的概念及常見的排序算法

? ? ? ? 排序在咱們日常生活中十分的常見,就好比是網上購物的時候通常能夠選擇按照什么排序,比如價格、評論數量、銷量等。那么接下來咱們就來了解一些關于排序的概念。

????????排序:所謂排序,就是使一串記錄,按照其中的某個或某些關鍵字的大小,遞增或遞減的排列起來的操作。

????????穩定性:假定在待排序的記錄序列中,存在多個具有相同的關鍵字的記錄,若經過排序,這些記錄的相對次 序保持不變,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,則稱這種排 序算法是穩定的;否則稱為不穩定的。

????????內部排序:數據元素全部放在內存中的排序。

????????外部排序:數據元素太多不能同時放在內存中,根據排序過程的要求不斷地在內外存之間移動數據的排序。

? ? ? ? 排序也是有很多算法的,一下是常見的排序算法:

? ? ? ? 接下來咱們分別來說一說這些個常見的排序。

2.插入排序

? ? ? ? 2.1直接插入排序

? ? ? ? 插入排序就像是打撲克牌摸牌時的整理牌的動作,取出一張牌,插在兩張牌之間形成升序,以此往復,直至牌被整理好。咱們再來觀察一下直接插入排序排升序的動圖模擬。

? ? ? ? 首先,咱們來討論開始情況,初始時,認為第一個元素已排好,①與②比較,如果②大,認為①②已經排好,接下來以②開始和③比較;如果②小,則取出②,①挪到②的位置,②向后沒有數可以比較,②停在0的位置,認為①②排好,接下來以②開始和③比較。

? ? ? ? 接下來,咱們假設一共有n個元素,設end為已排好的序列的最后一項的位置,提前存好end+1的內容賦值到tmp。end與end+1進行比較:

如果end+1比end要大,那么視為排好,end+1成為新的end繼續與新的end+1進行比較

如果end+1比end要小,end的內容賦值到end+1中,這時候的end缺少數據,咱們假象tmp停在上面等待加入,接著end--,將end和tmp進行比較:

????????①如果tmp大于end,就說明前面的數據全都比tmp小,無需再比較,tmp停下比較,停在end+1的位置(end是--后的end)

????????②如果tmp小于end,那么end的值賦值在end+1的位置(tmp預備賦值的地方),想象tmp懸在end上方,end--,以此往復,直到end減到了-1,或者tmp碰到了比他小的數為止,最終tmp賦值在了end+1處。

? ? ? ? 以上就是對于單趟排序的分析,以下是插入排序的具體內容,可見插入排序的時間復雜度是O(N^2).

void InsertSort(int* a, int n)
{for(int i=0;i<n-1;i++){//初始時,認為第一個數據已經排好int end = i;//提前存下end+1的內容int tmp = a[end + 1];//end為-1的時候結束while (end >= 0){//tmp小,還沒有找到自己的位置if (tmp < a[end]){//end來到end+1的位置a[end + 1] = a[end];end--;}else//tmp大,說明已經找到位置了,不用繼續遍歷,退出循環{break;}}//將tmp賦值在end+1的位置a[end + 1] = tmp;}
}

? ? ? ? 2.2希爾排序

? ? ? ? 希爾排序是以插入排序為基礎的一種排序,效率比直接排序更高,時間復雜度大概為O(N^1.3),其思想是:①通過預排序使數據趨于有序;②用插入排序排好。

? ? ? ? 假設一個整型gap,那么預排序就是從0開始,每隔一個gap取一個數(不越界取),取完后進行一次插入排序,然后在從1開始,每隔一個gap取一個數,繼續插入排序,直到取完,也就是把插入排序改成如下,gap的值可以為任意值(但是要小于元素個數)。

gap = 3;
for (int i = 0; i < n - gap; i++)
{int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;
}

? ? ? ? 通過預排序,可以快速將前面較大的數據轉移到后面。但僅有一個gap的,對數據的有序化有限,此時,就可以遍歷gap的值來增強有序化,那么gap的初值選什么合適呢?gap值選大了就容易漏掉很多數據,取小了效率就低,于是有大佬研究,gap取元素個數的三分之一效率會較高。所以當元素個數為n時,gap=n,gap=n/3.

? ? ? ? 都到這里了,肯定就有人發現了,當gap=1的時候不就是插入排序嗎!那能不能把預排序和插入排序結合起來呢?可以是可以,但是咱們要確保gap的最后取值是1呀,于是對gap有了一點改進:gap=gap/3+1。一眼看上去可能看不出什么苗頭,但是只要代值進去就會發現,gap最后都是1.

? ? ? ? 那么最終的代碼如下,

void TestShellSort(int* a, int n)
{int gap = n;while(gap>1){gap = gap / 3 + 1;for (int i = 0; i < n - gap; i++){int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}
}

3.選擇排序

? ? ? ? 3.1選擇排序

? ? ? ? 選擇排序的思想:每一次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始位置,直到全部待排序的數據元素排完。

? ? ? ? 以排升序,找小數為例,可以使用假設法找到小數下標,先設0為最小數,和1進行比較,如果0小,那么不變,如果1小,那么下標改為1,遍歷一趟之后咱們就能將最小的值放在開頭,單層循環結束后只需要重新設最小數就能完成排序,于是可以有以下代碼,時間復雜度為O(N).

void SeSort(int* a, int n)
{int left = 0;while (left < n){int min = left;for (int i = left+1; i < n; i++){if (a[min] > a[i])min = i;}Swap(&a[min], &a[left]);left++;}
}

? ? ? ? 此時提出一個問題,能不能同時找到最大值和最小值放到左右兩邊呢?這當然是可以的,但如果最大值位于最小值將要換到的地方或者是最小值位于最大值將要換到的地方呢?咱們需要注意這點,并在交換的時候注意更新數據。

void SelectSort(int* a, int n)
{int right = n-1;int left = 0;while(right>left){int max = left;int min = left;for (int i = left+1; i < n-left; i++){if (a[i] > a[max]){max = i;}if (a[i] < a[min]){min = i;}}Swap(&a[min], &a[left]);//如果重疊,那么更新數據if (max == left)max = min;Swap(&a[max], &a[right]);right--;left++;}
}

????????3.2堆排序

????????堆排序是指利用堆積樹(堆)這種數據結構所設計的一種排序算法,它是選擇排序的一種。它是通過堆來進行選擇數據需要注意的是排升序要建大堆排降序建小堆。其時間復雜度為O(nlogn)。

? ? ? ? 在二叉樹部分也有提過,其核心就是向下調整算法建堆,再將根與最后一個元素交換,調整堆的大小,在向下調整成新的堆,循環操作得到排好的數據。

? ? ? ? 至于向下調整算法建堆可以參見往篇,而排序的過程也只是簡單的控制定義域。

void AdjustDwon(int* a, int n, int root)
{//向下調整,大堆//root*2+1為孩子節點,如果孩子節點存在則循環繼續while(root * 2 + 1<n){//找到兩個孩子中大的那個int child = root * 2 + 1;if (child+1<n && a[child] < a[child + 1]){child = child + 1;}if (child<n && a[child] > a[root]){Swap(&a[child], &a[root]);}root = child;}
}void HeapSort(int* a, int n)
{//最后一個節點的父節點int parent = (n - 1 - 1) / 2;//向下調整建堆for (int i = parent; i >= 0; i--){AdjustDwon(a, n, i);}//選擇,挑出大的數據for (int i = n - 1; i > 0; i--){Swap(&a[0], &a[i]);AdjustDwon(a, i - 1, 0);}
}

? ? ? ? 今天的排序就到這里啦!至于剩下的排序就留到下篇吧!

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

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

相關文章

文獻閱讀筆記:RS電子戰測試與測量技術文檔

信息來源&#xff1a;羅德與施瓦茨&#xff08;Rohde & Schwarz&#xff09;公司關于電子戰&#xff08;Electronic Warfare, EW&#xff09;測試與測量解決方案專業技術文檔。 該文檔由臺灣地區應用工程師Mike Wu撰寫&#xff0c;核心圍繞電子戰基礎、雷達系統、實戰應用及…

別再糾結 Postman 和 Apifox 了!這款開源神器讓 API 測試更簡單

別再糾結 Postman 和 Apifox 了&#xff01;這款開源神器讓 API 測試更簡單&#x1f525; 作為一名開發者&#xff0c;你是否還在為選擇 API 測試工具而糾結&#xff1f;Postman 太重、Apifox 要聯網、付費功能限制多&#xff1f;今天給大家推薦一款完全免費的開源替代方案 ——…

微調神器LLaMA-Factory官方保姆級教程來了,從環境搭建到模型訓練評估全覆蓋

1. 項目背景 開源大模型如LLaMA&#xff0c;Qwen&#xff0c;Baichuan等主要都是使用通用數據進行訓練而來&#xff0c;其對于不同下游的使用場景和垂直領域的效果有待進一步提升&#xff0c;衍生出了微調訓練相關的需求&#xff0c;包含預訓練&#xff08;pt&#xff09;&…

創建其他服務器賬號

? 在 /home74 下創建新用戶的完整步驟1. 創建用戶并指定 home 目錄和 shellsudo useradd -m -d /home74/USERNAME -s /bin/bash USERNAME-m&#xff1a;自動創建目錄并復制 /etc/skel 默認配置文件&#xff08;.bashrc 等&#xff09;。-d&#xff1a;指定用戶 home 路徑&…

【WebGIS】Vue3使用 VueLeaflet + 天地圖 搭建地圖可視化平臺(基礎用法)

初始化 創建項目 nodejs 18.0.6npm 9.5.1 引入地圖服務 VueLeaflet GitHub - vue-leaflet/vue-leaflet&#xff1a; vue-leaflet 與 vue3 兼容 Vue Leaflet (vue2-leaflet) package.josn安裝版本 直接添加四個依賴 {// ..."scripts": {// ...},"depen…

OpenCV 開發 -- 圖像閾值處理

文章目錄[toc]1 基本概念2 簡單閾值處理cv2.threshold3 自適應閾值處理cv2.adaptiveThreshold更多精彩內容&#x1f449;內容導航 &#x1f448;&#x1f449;OpenCV開發 &#x1f448;1 基本概念 圖像閾值處理&#xff08;Thresholding&#xff09;是圖像處理中的一種基本技術…

單串口服務器-工業級串口聯網解決方案

在工業自動化、智能電網、環境監測等領域&#xff0c;傳統串口設備&#xff08;如PLC、傳感器、儀表等&#xff09;的網絡化升級需求日益增長。博為智能單串口服務器憑借高性能硬件架構、多協議支持和工業級可靠性&#xff0c;為RS485設備提供穩定、高效的TCP/IP網絡接入能力&a…

第 9 篇:深入淺出學 Java 語言(JDK8 版)—— 吃透泛型機制,筑牢 Java 類型安全防線

簡介&#xff1a;聚焦 Java 泛型這一“類型安全保障”核心技術&#xff0c;從泛型解決的核心痛點&#xff08;非泛型代碼的運行時類型錯誤、強制類型轉換冗余&#xff09;切入&#xff0c;詳解泛型的本質&#xff08;參數化類型&#xff09;、核心用法&#xff08;泛型類/接口/…

MySQL和Redis的數據一致性問題與業界常見解法

一、為什么會出現數據不一致&#xff1f; 根本原因在于&#xff1a;這是一個涉及兩個獨立存儲系統的數據更新操作&#xff0c;它無法被包裝成一個原子操作&#xff08;分布式事務&#xff09;。更新數據庫和更新緩存是兩個獨立的步驟&#xff0c;無論在代碼中如何排列這兩個步驟…

coolshell文章閱讀摘抄

coolshell文章閱讀摘抄打好基礎學好英語限制你的不是其它人&#xff0c;也不是環境&#xff0c;而是自己Java打好基礎 程序語言&#xff1a;語言的原理&#xff0c;類庫的實現&#xff0c;編程技術&#xff08;并發、異步等&#xff09;&#xff0c;編程范式&#xff0c;設計模…

數據庫造神計劃第六天---增刪改查(CRUD)(2)

&#x1f525;個人主頁&#xff1a;尋星探路 &#x1f3ac;作者簡介&#xff1a;Java研發方向學習者 &#x1f4d6;個人專欄&#xff1a;《從青銅到王者&#xff0c;就差這講數據結構&#xff01;&#xff01;&#xff01;》、 《JAVA&#xff08;SE&#xff09;----如此簡單&a…

使用Rust實現服務配置/注冊中心

Conreg 使用 Rust 實現的配置與注冊中心&#xff0c;參考了 Nacos 的設計&#xff0c;簡單易用&#xff0c;使用 Raft 保證集群節點數據一致性。 支持的平臺&#xff1a; UbuntuCentOS其他常見的 Linux 發行版&#xff08;我們使用 musl 編譯&#xff0c;理論上支持所有主流…

三色標記算法

在 JVM 并發垃圾收集&#xff08;GC&#xff09;中&#xff0c;三色標記算法是實現 “GC 線程與用戶線程并行執行” 的關鍵技術&#xff0c;它解決了并發場景下 “如何準確標記存活對象” 的核心問題&#xff0c;是 CMS、G1 等現代收集器的底層基礎。一、三色標記的核心&#x…

OpenStack 管理與基礎操作學習筆記(一):角色、用戶及項目管理實踐

OpenStack實驗 OpenStack命令 admin-openrc.sh 進入管理員視圖查看當前 OpenStack 中的項目列表&#xff0c;驗證是否已經登錄成功切換用戶 修改文件切換用戶上傳文件切換用戶OpenStack 認證管理 實驗介紹 通過 OpenStack Dashboard 和 OpenStack CLI 兩種方式創建角色、用戶、…

直接查找試卷且可以免費下載

有什么網站可以直接查找試卷且可以免費下載&#xff1f; SearXNG開源元搜索引擎 This website shows the SearXNG public instances searx一個可定制的搜索引擎 分享一個基于Blockstack的DApp-searx,一個可定制的搜索引擎。 1- 鏈接 官網地址&#xff1a;https://searx.worl…

【獨立版】智創云享知識付費小程序 v5.0.23+小程序 搭建教程

介紹智創云享知識付費小程序v5.0.23 含PC、小程序、H5 、前端&#xff0c;系統獨立版已修復已知bug問題。框架是一款基于ThinkPHP框架開發的虛擬資源知識付費小程序&#xff0c;為廣大創業者、自媒體及培訓機構提供知識付費、內容付費、資源變現等領域的行業解決方案&#xff1…

布爾運算-區間dp

面試題 08.14. 布爾運算 - 力扣&#xff08;LeetCode&#xff09; Solution 這題的思路比較直接&#xff0c;就是枚舉最后一個進行計算的運算符&#xff0c;但是在實現過程中需要注意&#xff0c;定義范式f(l,r)表示l到r范圍&#xff0c;l和r必須為數字&#xff0c;l1,r-1為運…

MyBatis-Plus 擴展全局方法

1.文件內容package com.ruoyi.business.mybatisplus.base;import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.extension.service.IService;import java.util.List;/*** 擴展的 Service 接口* 所有自定義 Service 接口都需要繼承此接口…

13.Linux OpenSSH 服務管理

文章目錄Linux OpenSSH 服務管理環境準備OpenSSH 服務介紹SSH 介紹SSH 建立連接的過程加密類型雙向加密過程使用 ssh 訪問遠端CLIssh 工具演示ssh工具配置文件配置 ssh 密鑰認證ssh 故障模擬故障模擬排故故障自定義 SSH 服務配置文件禁止 root 登錄禁止密碼登錄只允許特定用戶登…

速通ACM省銅第五天 賦源碼(MEX Count)

目錄 引言&#xff1a; MEX Count 題意分析 邏輯梳理 代碼實現 結語&#xff1a; 引言&#xff1a; 本來&#xff0c;今天我是想著出倆題或三題題解的&#xff0c;但是在打第一題的時候就天塌了&#xff0c;導致今天就只搓了一道題&#xff0c;這題的難度在CF中為1300的水準&…