數據結構:選擇排序

簡單選擇排序

選擇排序是一種簡單直觀的排序算法。首先在未排序序列中找到最大(最小)的元素,存放到排序學列的其實位置,然后在剩余的未排序的元素中尋找最小(最大)元素,存放在已排序序列的后面

算法步驟

  1. 在未排序序列中找到最大(小)元素,存放在排序序列的起始位置
  2. 再從剩余的未排序序列中找到最大(小)元素,然后存放在已排序序列的后面
  3. 重復上訴第二步驟,直至排序結束

算法理解

例如對無序表{56,12,80,91,20}采用簡單選擇排序算法進行排序,具體過程為:

  • 第一次遍歷時,從下標為 1 的位置即 56 開始,找出關鍵字值最小的記錄 12,同下標為 0 的關鍵字 56 交換位置:

    在這里插入圖片描述

  • 第二次遍歷時,從下標為 2 的位置即 56 開始,找出最小值 20,同下標為 2 的關鍵字 56 互換位置:

    在這里插入圖片描述

  • 第三次遍歷時,從下標為 3 的位置即 80 開始,找出最小值 56,同下標為 3 的關鍵字 80 互換位置:

    在這里插入圖片描述

  • 第四次遍歷時,從下標為 4 的位置即 91 開始,找出最小是 80,同下標為 4 的關鍵字 91 互換位置:

    在這里插入圖片描述

  • 到此簡單選擇排序算法完成,無序表變為有序表。

代碼實現

#include "iostream"
using namespace std;#define MAX 9
//單個記錄的結構體
typedef struct {int key;
}SqNote;
//記錄表的結構體
typedef struct {SqNote r[MAX];int length;
}SqList;
//交換兩個記錄的位置
void swap(SqNote *a,SqNote *b){int key=a->key;a->key=b->key;b->key=key;
}
//查找表中關鍵字的最小值
int SelectMinKey(SqList *L,int i){int min=i;//從下標為 i+1 開始,一直遍歷至最后一個關鍵字,找到最小值所在的位置while (i+1<L->length) {if (L->r[min].key>L->r[i+1].key) {min=i+1;}i++;}return min;
}
//簡單選擇排序算法實現函數
void SelectSort(SqList * L){for (int i=0; i<L->length; i++) {//查找第 i 的位置所要放置的最小值的位置int j=SelectMinKey(L,i);//如果 j 和 i 不相等,說明最小值不在下標為 i 的位置,需要交換if (i!=j) {swap(&(L->r[i]),&(L->r[j]));}}
}
int main() {SqList *L = new SqList;L->length=8;L->r[0].key=49;L->r[1].key=38;L->r[2].key=65;L->r[3].key=97;L->r[4].key=76;L->r[5].key=13;L->r[6].key=27;L->r[7].key=49;SelectSort(L);for (int i=0; i<L->length; i++) {cout << L->r[i].key << " ";}return 0;
}

代碼實現

13 27 38 49 49 65 76 97

樹形選擇排序

樹形選擇排序(又稱“錦標賽排序”),是一種按照錦標賽的思想進行選擇排序的方法,即所有記錄采取兩兩分組,篩選出較小(較大)的值;然后從篩選出的較小(較大)值中再兩兩分組選出更小(更大)值,依次類推,直到最后選出一個最小(最大)值。同樣可以采用此方式篩選出次小(次大)值等

算法理解

整個排序的過程,可以用一棵具有 n 個葉子結點的完全二叉樹表示。例如對無序表{49,38,65,97,76,13,27,49}采用樹形選擇的方式排序,過程如下:

  • 首先將無序表中的記錄采用兩兩分組,篩選出各組中的較小值(如圖 1 中的(a)過程);然后將篩選出的較小值兩兩分組,篩選出更小的值,以此類推(如圖 1 中的(b)(c)過程),最終整棵樹的根結點中的關鍵字即為最小關鍵字:

在這里插入圖片描述

圖 1 樹形選擇排序(一)

  • 篩選出關鍵字 13 之后,繼續重復此方式找到剩余記錄中的最小值,此時由于關鍵字 13 已經篩選完成,需要將關鍵字 13 改為“最大值”,繼續重復此過程,如圖 2 所示: 圖 2 樹形選擇排序(二)

    在這里插入圖片描述

通過不斷地重復此過程,可依次篩選出從小到大的所有關鍵字。該算法的時間復雜度為O(nlogn),同簡單選擇排序相比,該算法減少了不同記錄之間的比較次數,但是程序運行所需要的空間較多。

代碼實現

#include "iostream"
using namespace std;
#define N 8
void TreeSelectionSort(int *mData)
{int MinValue = 0;int tree[N * 4]; // 樹的大小int max, maxIndex, treeSize;int i, n = N, baseSize = 1;while (baseSize < n)baseSize *= 2;treeSize = baseSize * 2 - 1;for (i = 0; i < n; i++) {//將要排的數字填到樹上tree[treeSize - i] = mData[i];}for (; i < baseSize; i++) {//其余的地方都填上最小值tree[treeSize - i] = MinValue;}// 構造一棵樹,大的值向上構造for (i = treeSize; i > 1; i -= 2){tree[i / 2] = (tree[i] > tree[i - 1] ? tree[i] : tree[i - 1]);}n -= 1;while (n != -1){max = tree[1];        //樹頂為最大值mData[n--] = max;     //從大到小倒著貼到原數組上maxIndex = treeSize;  //最大值下標while (tree[maxIndex] != max) {maxIndex--;}//找最大值下標tree[maxIndex] = MinValue;while (maxIndex > 1) {if (maxIndex % 2 == 0) {tree[maxIndex / 2] = (tree[maxIndex] > tree[maxIndex + 1] ? tree[maxIndex] : tree[maxIndex + 1]);}else {tree[maxIndex / 2] = (tree[maxIndex] > tree[maxIndex - 1] ? tree[maxIndex] : tree[maxIndex - 1]);}maxIndex /= 2;}}
}
int main()
{int a[N] = {49,38,65,97,76,13,27,49};TreeSelectionSort(a);for (int i = 0; i < N; i++) {cout << a[i] << " ";}return 0;
}

運行結果

13 27 38 49 49 65 76 97

堆排序

堆排序 ( H e a p s o r t ) (Heapsort) (Heapsort)是指利用堆來實現的一種排序算法。堆積是一個近似完全二叉樹的結構,并同時滿足堆積的性質:即子結點的鍵值或索引總是小于(或者大于)它的父節點。堆排序可以說是一種利用堆的概念來排序的選擇排序。堆排序的平均時間復雜度為 O ( n l o g n ) O(nlogn) O(nlogn)。分為兩種方法:

  1. 大頂堆:每個節點的值都大于或等于其子節點的值,在堆排序算法中用于升序排列;
  2. 小頂堆:每個節點的值都小于或等于其子節點的值,在堆排序算法中用于降序排列;

在這里插入圖片描述

算法思想

了解了堆的基本性質之后,我們就可以看堆排序的基本思想。

  1. 將未排序的序列構造成大(或者小)頂堆,根據堆的性質我們可以找到序列中的最大(或者最小)值
  2. 把堆首和堆尾互換,并把堆的大小減 1 1 1
  3. 重復上面的步驟,直到堆的大小為 1 1 1

在這里插入圖片描述

在這里插入圖片描述

代碼實現

#include "iostream"
using namespace std;
#define MAX 9
//單個記錄的結構體
typedef struct {int key;
}SqNote;
//記錄表的結構體
typedef struct {SqNote r[MAX];int length;
}SqList;
//將以 r[s]為根結點的子樹構成堆,堆中每個根結點的值都比其孩子結點的值大
void HeapAdjust(SqList * H,int s,int m){SqNote rc=H->r[s];//先對操作位置上的結點數據進行保存,放置后序移動元素丟失。//對于第 s 個結點,篩選一直到葉子結點結束for (int j=2*s; j<=m; j*=2) {//找到值最大的孩子結點if (j+1<m && (H->r[j].key<H->r[j+1].key)) {j++;}//如果當前結點比最大的孩子結點的值還大,則不需要對此結點進行篩選,直接略過if (!(rc.key<H->r[j].key)) {break;}//如果當前結點的值比孩子結點中最大的值小,則將最大的值移至該結點,由于 rc 記錄著該結點的值,所以該結點的值不會丟失H->r[s]=H->r[j];s=j;//s相當于指針的作用,指向其孩子結點,繼續進行篩選}H->r[s]=rc;//最終需將rc的值添加到正確的位置
}
//交換兩個記錄的位置
void swap(SqNote *a,SqNote *b){int key=a->key;a->key=b->key;b->key=key;
}
void HeapSort(SqList *H){//構建堆的過程for (int i=H->length/2; i>0; i--) {//對于有孩子結點的根結點進行篩選HeapAdjust(H, i, H->length);}//通過不斷地篩選出最大值,同時不斷地進行篩選剩余元素for (int i=H->length; i>1; i--) {//交換過程,即為將選出的最大值進行保存大表的最后,同時用最后位置上的元素進行替換,為下一次篩選做準備swap(&(H->r[1]), &(H->r[i]));//進行篩選次最大值的工作HeapAdjust(H, 1, i-1);}
}int main() {SqList *L = new SqList ;L->length=8;L->r[1].key=49;L->r[2].key=38;L->r[3].key=65;L->r[4].key=97;L->r[5].key=76;L->r[6].key=13;L->r[7].key=27;L->r[8].key=49;HeapSort(L);for (int i=1; i<=L->length; i++) {cout << L->r[i].key << " ";}return 0;
}

運行結果

13 27 38 49 49 65 76 97

注意:堆排序相對于樹形選擇排序,其只需要一個用于記錄交換(rc)的輔助存儲空間,比樹形選擇排序的運行空間更小。

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

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

相關文章

高等數學:牛頓迭代發解方程

現在高數也要介紹牛頓法了&#xff0c;一般都是從幾何上直接以“切線法”直接引入的。這種引入方式的確很簡單&#xff0c;但如果脫離深入一點的分析就不大容易解釋后面的事情。所以就在想怎么更直接地從分析的角度來一條線貫穿&#xff0c;把整個過程說一說。 文章目錄 一、牛…

【深度學習】PyTorch快速入門

【深度學習】學習PyTorch基礎 介紹PyTorch 深度學習框架是一種軟件工具&#xff0c;旨在簡化和加速構建、訓練和部署深度學習模型的過程。深度學習框架提供了一系列的函數、類和工具&#xff0c;用于定義、優化和執行各種深度神經網絡模型。這些框架幫助研究人員和開發人員專注…

漏洞+常見漏洞修復建議

一、漏洞級別 高級別漏洞&#xff1a;大部分遠程和本地管理員權限漏洞 中級別漏洞&#xff1a;大部分普通用戶權限、權限提升、讀懂受限文件、遠程和本杜漏洞、拒絕服務漏洞 低級別漏洞&#xff1a;大部分遠程非授權文件存取、口令恢復、欺騙、信息泄露漏洞 二、漏洞掃描的…

Kotlin Lambda和高階函數

Lambda和高階函數 本文鏈接&#xff1a; 文章目錄 Lambda和高階函數 lambda輸出&#xff08;返回類型&#xff09;深入探究泛型 inline原理探究 高階函數集合、泛型自己實現Kotlin內置函數 擴展函數原理companion object 原理 > 靜態內部類函數式編程 lambda 1、lambda的由…

Flink流批一體計算(13):PyFlink Tabel API之SQL DDL

1. TableEnvironment 創建 TableEnvironment from pyflink.table import Environmentsettings, TableEnvironment# create a streaming TableEnvironmentenv_settings Environmentsettings.in_streaming_mode()table_env TableEnvironment.create(env_settings)# or create…

嵌入式Linux開發實操(九):CAN接口開發

前言: CAN網絡在汽車中的使用可以說相當廣泛。而CAN網絡需要的收發器最常用的就是NXP 的TJA1042: CAN網絡:

605. 種花問題

鏈接 假設有一個很長的花壇&#xff0c;一部分地塊種植了花&#xff0c;另一部分卻沒有。可是&#xff0c;花不能種植在相鄰的地塊上&#xff0c;它們會爭奪水源&#xff0c;兩者都會死去。給你一個整數數組 flowerbed 表示花壇&#xff0c;由若干 0 和 1 組成&#xff0c;其中…

8/16總結

WebSocket是雙向通信協議&#xff0c;模擬Socket協議&#xff0c;可以雙向發送或者接收信息 而Http是單向的 WebSocket是需要瀏覽器和服務器握手進行建立連接的 而http是瀏覽器發起向服務器的連接&#xff0c;服務器預先并不知道這個連接 WebSocket在建立握手時&#xff0c;數…

Python3內置函數大全

吐血整理 Python3內置函數大全 1.abs()函數2.all()函數3.any()函數4.ascii()函數5.bin()函數6.bool()函數7.bytes()函數8.challable()函數9.chr()函數10.classmethod()函數11.complex()函數12.complie()函數13.delattr()函數14.dict()函數15.dir()函數16.divmod()函數17.enumer…

注解@JsonInclude

注解JsonInclude 1. 注解由來 JsonInclude是一個用于Java類中字段或方法的注解&#xff0c;它來自于Jackson庫。Jackson庫是一個用于處理JSON數據的流行開源庫&#xff0c;在Java對象和JSON之間進行序列化和反序列化時經常被使用。 2. 注解示例 下面是JsonInclude注解的一個…

【kubernetes】Pod控制器

目錄 Pod控制器及其功用 pod控制器有多種類型 1、ReplicaSet ReplicaSet主要三個組件組成 2、Deployment 3、DaemonSet 4、StatefulSet 5、Job 6、Cronjob Pod與控制器之間的關系 1、Deployment 查看控制器配置 查看歷史版本 2、SatefulSet 為什么要有headless&…

2023-08-18力扣每日一題

鏈接&#xff1a; 1388. 3n 塊披薩 題意&#xff1a; 一個長度3n的環&#xff0c;選n次數字&#xff0c;每次選完以后相鄰的數字會消失&#xff0c;求選取結果最大值 解&#xff1a; 這波是~~&#xff08;ctrl&#xff09;CV工程師了~~ 核心思想是選取n個不相鄰的元素一定…

無涯教程-Perl - splice函數

描述 此函數從LENGTH元素的OFFSET元素中刪除ARRAY元素,如果指定,則用LIST替換刪除的元素。如果省略LENGTH,則從OFFSET開始刪除所有內容。 語法 以下是此函數的簡單語法- splice ARRAY, OFFSET, LENGTH, LISTsplice ARRAY, OFFSET, LENGTHsplice ARRAY, OFFSET返回值 該函數…

Vue 項目運行 npm install 時,卡在 sill idealTree buildDeps 沒有反應

解決方法&#xff1a;切換到淘寶鏡像。 以下是之前安裝的 xmzs 包&#xff0c;用于控制切換淘寶鏡像。 該截圖是之前其他項目切換淘寶鏡像的截圖。 切換鏡像后&#xff0c;順利執行 npm install 。

生成國密密鑰對

在線生成國密密鑰對 生成的密鑰對要妥善保管&#xff0c;丟失是無法找回的。

selinux

一、selinux的說明 二、selinux的工作原理 三、selinux的啟動、關閉與查看 Enforcing和permissive都是臨時的&#xff0c;重啟還是依據配置文件中&#xff0c;禁用selinux&#xff0c;修改配置文件&#xff1a; 之后重啟生效 四、selinux對linux服務的影響

SpringBoot 接口調用出現亂碼解決 中文亂碼

SpringBoot 接口調用出現亂碼解決 package com.cxjg.mvc.util;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springfra…

相同數字的積木游戲

題目描述 題目描述 小華和小薇一起通過玩積木游戲學習數學。 他們有很多積木&#xff0c;每個積木塊上都有一個數字&#xff0c;積木塊上的數字可能相同。 小華隨機拿一些積木挨著排成一排&#xff0c;請小薇找到這排積木中數字相同目所處位置最遠的2塊積木塊&#xff0c;計算…

【JAVA】我們該如何規避代碼中可能出現的錯誤?(一)

個人主頁&#xff1a;【&#x1f60a;個人主頁】 系列專欄&#xff1a;【??初識JAVA】 文章目錄 前言三種類型的異常異常處理JAVA內置異常類Exception 類的層次 前言 異常是程序中的一些錯誤&#xff0c;但并不是所有的錯誤都是異常&#xff0c;并且錯誤有時候是可以避免的&…

【BASH】回顧與知識點梳理(三十三)

【BASH】回顧與知識點梳理 三十三 三十三. 認識系統服務 (daemons)33.1 什么是 daemon 與服務 (service)早期 System V 的 init 管理行為中 daemon 的主要分類 (Optional)systemd 使用的 unit 分類systemd 的配置文件放置目錄systemd 的 unit 類型分類說明 33.2 透過 systemctl…