01數據結構-歸并排序和計數排序

01數據結構-歸并排序和計數排序

  • 1.歸并排序
    • 1.1歸并排序概述
    • 1.2歸并排序的執行流程
      • 1.2.1遞(分裂)的過程
      • 1.2.2歸(合并)的過程
    • 1.3歸并排序的代碼實現
  • 2.計數排序
    • 2.1算法思想
    • 2.2計數排序的改進
      • 2.2.1優化1
      • 2.2.2優化2

1.歸并排序

1.1歸并排序概述

歸并排序,其排序的實現思想是先將所有的記錄分開,然后兩兩合并,在合并的過程中將其排好序,最終得到一個完整的序列。由于使用到的遞歸思想,我個人認為也可以叫遞歸排序。歸并排序非常適合大數據排序,大部分數據都在磁盤上,我們可以用歸并排序拆分,我們拆成可以在內存中保存的n個有序區間,往回寫到硬盤里,再進行合并這幾個有序序列的時候工作量就變小了。

1.2歸并排序的執行流程

1.不斷地將當前序列平均分割成兩個子序列:例如下面的序列,被分割成兩個子序列,注意實際寫代碼的時候可能不會完全分割成兩等份
在這里插入圖片描述
2.然后繼續將這些子序列分割成子序列,直到不能再分割位置。(序列中只剩下一個元素)
在這里插入圖片描述
2.接下來,在不斷的將兩個子序列合并成一個有序序列:也就是說,剛剛是拆分,現在是合并。
在這里插入圖片描述

合并的時候比較哪個序列的最小值更小就是真正的最小值,注意合并的7和8和上面分散的7和8是一個空間,我們是在原空間中排好序的,拆分完后我們沿路返回,只是方便大家看流程,在并的過程中我往下面畫的,整個過程和樹的DFS有點像,先處理完一邊,再去處理另一邊。

1.2.1遞(分裂)的過程

在這里插入圖片描述
我們設置兩個left和right兩個標志位,不斷地分割序列,直到left==right,說明無法繼續分割了,開始歸回來,圖中我沒有畫完全,只是做個展示。

1.2.2歸(合并)的過程

在這里插入圖片描述
最右邊是我們要排序的序列的原空間,我們創建兩個獨立的空間用來存分裂后的序列,并創建兩個指針指向兩個序列空間中的最小值元素。第一次比較兩個序列中指針指向的更小值為3,把它放入原序列的空間的第一號元素,在哪個空間中放的序列我們就把哪個空間的最小值指針往右邊移動一位,另一個空間中的最小值元素指針不動,然后再次比較兩個空間中指針指向的元素的較小值依次類推直到把其中某一個空間中的值全部放入了原空間中,再把另一個空間中的所有值排在后面即可。

1.3歸并排序的代碼實現

遞進去拆分:

// 遞歸的分解table[left, right]區間
static void merge_loop(SortTable *table, int left, int right) {if (left >= right) {return;}int mid = (left + right) / 2;merge_loop(table, left, mid);merge_loop(table, mid + 1, right);// 區間拆分結束,合并兩個子區間merge(table, left, mid, right);
}

合并過程:

// merge合并過程
static void merge(SortTable *table, int left, int mid, int right) {int n1 = mid - left + 1;        // 左邊區間的個數int n2 = right - mid;           // 右邊區間的個數// 分配aux1和aux2,將已經有序的左區間和已經有序的右區間 初始化臨時區域Element *aux1 = malloc(sizeof(Element) * n1);if (aux1 == NULL) {return;}Element *aux2 = malloc(sizeof(Element) * n2);if (aux2 == NULL) {free(aux1);return;}for (int i = 0; i < n1; i++) {aux1[i] = table->data[left + i];}for (int i = 0; i < n2; ++i) {aux2[i] = table->data[mid + 1 + i];}// 將臨時的有序空間aux1和aux2進行歸并int i = 0;          // 標記aux1區間待查找的位置int j = 0;          // 標記aux2區間待查找的位置int k = left;       // 標記原空間存放結果的區域位置while (i < n1 && j < n2) {if (aux1[i].key <= aux2[j].key) {table->data[k] = aux1[i];++i;} else if (aux1[i].key > aux2[j].key) {table->data[k] = aux2[j];++j;}k++;}// 判斷究竟是aux1還是aux2區域遍歷結束while (i < n1) {table->data[k++] = aux1[i++];}while (j < n2) {table->data[k++] = aux2[j++];}free(aux1);free(aux2);
}

注意這里初始化的時候要加上序列左邊的基地址。

接口調用:

/* 歸并排序:從上往下,從下往上兩個過程* 從上往下的過程:*  a. 分解 -- 將當前區間一分為二*  b. 求解 -- 遞歸對兩個子區間a[low...mid] 和 a[mid+1...high]進行歸并排序*/
void mergeSort(SortTable *table) {merge_loop(table, 0, table->length - 1);
}

最后來測一下:

#include "mergeSort.h"int main() {int n = 10000;SortTable *table = generateRandomArray(n, 0, n + 5000);testSort("Merge Sort", mergeSort, table);releaseSortTable(table);return 0;
}

結果:

D:\work\DataStruct\cmake-build-debug\04_Sort\MergeSort.exe
Merge Sort cost time: 0.002000s.進程已結束,退出代碼為 0

時間復雜度也是接近O(nlogn)。

2.計數排序

計數排序(Counting Sort)是一種針對于特定范圍之間的整數進行排序的算法。它通過統計給定數組中不同元素的數量(類似于哈希映射),然后對映射后的數組進行排序輸出即可。(計數排序在某些情況下比快速排序還要快)

2.1算法思想

我們以數組 [1,4,1,2,5,2,4,1,8] 為例進行說明。

第一步:建立一個初始化為 0 ,?度為 9 (原始數組中的最大值 8 加 1) 的數組 count[]

第二步:遍歷數組[1,4,1,2,5,2,4,1,8],訪問第一個元素1,然后將數組標為1的元素加1,表示當前1出現了1此,即count[1]=1;

依次遍歷,對count進行統計。
在這里插入圖片描述

2.2計數排序的改進

  • 無法對負數進行排序
  • 極其浪費空間
  • 是一個不穩定排序

2.2.1優化1

只要不再以數列的[最大值+1]作為統計數組的長度,而是以數列[最大值-最小值+1]作為統計數組的長度即可。數列最小值作為一個偏移量,用于計算整數在統計數組中的下表

2.2.2優化2

為了使計數排序穩定,我們從統計數組的第2個元素開始,每一個元素都加上前面元素之和,相加的目的是讓統計數組存儲的元素值,等于對應整數的最終排序位置的序號,遍歷的時候從后向前遍歷原數組(在填充輸出數組時)來保證穩定性。

計數排序了解一下即可,還有一些排序比如選擇排序,桶排序我就不一一寫了,大家可以自己去看,大概先寫這些吧,今天的博客就先寫到這,謝謝您的觀看。

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

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

相關文章

SQL注入2----(sql注入數據類型分類)

一.前言本章節我們來講解一下sql注入的分類&#xff0c;主要分為四類&#xff0c;數字型、字符型、搜索型、xx型。二.數字型數字型注入的時候&#xff0c;是不需要考慮單\雙引號閉合問題的&#xff0c;因為sql語句中的數字是不需要用引號括起來的&#xff0c;如下mysql> sel…

Elasticsearch Rails 實戰全指南(elasticsearch-rails / elasticsearch-model)

一、背景與生態總覽 elasticsearch-rails&#xff1a;面向 Rails 的“伴生庫”&#xff0c;為 Rails 項目帶來 Rake 任務、日志埋點、模板等特性。elasticsearch-model&#xff1a;把 ES 能力“混入”到 Ruby 模型&#xff08;ActiveRecord/Mongoid&#xff09;&#xff0c;提供…

第三階段數據庫-2:數據庫中的sql語句

1_數據庫操作&#xff08;1&#xff09;注釋&#xff1a;-- 單行注釋 /**/ 多行注釋&#xff08;2&#xff09;創建數據庫&#xff1a;create database 數據庫名-- create database 數據庫名 create database db_first;(3&#xff09;查詢數據庫&#xff1a;if exsists(select…

python中的filter函數

目錄 定義與參數說明 特點 使用場景 常用操作 篩選偶數 去除空字符串 篩選正數 篩選字典 配合集合與元組 注意事項 定義與參數說明 filter函數是Python內置的高階函數之一&#xff0c;用于篩選可迭代對象中的元素&#xff0c;根據返回值的布爾結果&#xff08;True 或…

BERT(Bidirectional Encoder Representations from Transformers)模型詳解

一、BERT 簡介BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;是由 Google 在 2018 年提出的一種預訓練語言表示模型。它基于 Transformer 編碼器結構&#xff0c;首次提出了 雙向上下文建模 的方法&#xff0c;大幅度提升了自然語言處理…

【開題答辯全過程】以 基于Springboot+微信小程序的網上家教預約系統的設計與實現-開題為例,包含答辯的問題和答案

個人簡介&#xff1a;一名14年經驗的資深畢設內行人&#xff0c;語言擅長Java、php、微信小程序、Python、Golang、安卓Android等開發項目包括大數據、深度學習、網站、小程序、安卓、算法。平常會做一些項目定制化開發、代碼講解、答辯教學、文檔編寫、也懂一些降重方面的技巧…

課小悅系列智能耳機上市,用硬核科技為教育賦能

在人工智能與教育深度融合的浪潮中&#xff0c;深圳課小悅科技有限公司以“智慧教育專家”的姿態嶄露頭角。這家深耕智能教育硬件的創新企業&#xff0c;于2025年8月正式推出革命性產品H360PRO系列教考耳機&#xff0c;為語言學習場景提供顛覆性解決方案。創新基因&#xff1a;…

[react] class Component and function Component

我對react的用法理解還一直停留在多年以前&#xff0c;說明這段時間我沒有更新react的知識。我大腦中記得還是使用Class Component this.setState&#xff0c;可是今天看了看react的文檔&#xff0c;發現怎么不一樣了&#xff0c;用的都是function useState的方式了。你知道這…

以太坊智能合約地址派生方式:EOA、CREATE 和 CREATE2

1. 引言 在以太坊上&#xff0c;智能合約可以通過以下三種方式之一進行部署&#xff1a; 1&#xff09;由外部賬戶&#xff08;Externally Owned Account, EOA&#xff09;發起交易&#xff0c;其中 to 字段設為 null&#xff0c;而 data 字段包含合約的初始化代碼。2&#x…

基于RISC-V架構的國產MCU在eVTOL領域的應用研究與挑戰分析

摘要電動垂直起降飛行器&#xff08;eVTOL&#xff09;作為未來城市空中交通的重要組成部分&#xff0c;對嵌入式控制系統的性能、可靠性和安全性提出了極高的要求。RISC-V作為一種新興的開源指令集架構&#xff0c;為國產微控制器&#xff08;MCU&#xff09;的研發和應用帶來…

深度學習中的“集體智慧”:Dropout技術詳解——不僅是防止過擬合,更是模型集成的革命

引言&#xff1a;從“過擬合”的噩夢說起 在訓練深度學習模型時&#xff0c;我們最常遇到也最頭疼的問題就是過擬合&#xff08;Overfitting&#xff09;。 想象一下&#xff0c;你是一位正在備考的學生&#xff1a; 欠擬合&#xff1a;你根本沒學進去&#xff0c;所有題都做錯…

在JavaScript中,比較兩個數組是否有相同元素(交集)的常用方法

方法1&#xff1a;使用 some() includes()&#xff08;適合小數組&#xff09;function haveCommonElements(arr1, arr2) {return arr1.some(item > arr2.includes(item)); }// 使用示例 const arrA [1, 2, 3]; const arrB [3, 4, 5]; console.log(haveCommonElements(ar…

心路歷程-Linux的系統破解詳細解說

CentOS7系統密碼破解 密碼破解是分兩種情況的&#xff1b;一種是在系統的界面內&#xff0c;一種就是不在系統的頁面&#xff1b; 今天我們就來聊聊這個系統破解的話題&#xff1b; 1.為什么需要破解密碼&#xff1f;–>那當然是忘記了密碼&#xff1b;需從新設置密碼 2.但是…

IDE和AHCI硬盤模式有什么區別

IDE&#xff08;Integrated Drive Electronics&#xff09;和 AHCI&#xff08;Advanced Host Controller Interface&#xff09;是硬盤控制器的工作模式&#xff0c;主要區別在于性能、功能兼容性以及對現代存儲設備的支持程度。以下是詳細對比和分析&#xff1a;一、本質區別…

【密碼學實戰】密碼實現安全測試基礎篇 . KAT(已知答案測試)技術解析與實踐

KAT 測試技術解析 在密碼算法的安全性驗證體系中&#xff0c;Known Answer Test&#xff08;KAT&#xff0c;已知答案測試&#xff09;是一項基礎且關鍵的技術。它通過 “已知輸入 - 預期輸出” 的確定性驗證邏輯&#xff0c;為密碼算法實現的正確性、合規性提供核心保障&…

如何用Redis作為消息隊列

說明&#xff1a;以前背八股文&#xff0c;早就知道 Redis 可以作為消息隊列&#xff0c;本文介紹如何實現用 Redis 作為消息隊列。 介紹 這里直接介紹 yudao 框架中的實現。yudao 是一套現成的開源系統框架&#xff0c;里面集成了許多基礎功能&#xff0c;我們可以在這基礎上…

解決 uniapp 修改index.html文件不生效的問題

業務場景&#xff1a;需要在H5網站設置追蹤用戶行為&#xff08;即埋點&#xff09;的script代碼。 問題&#xff1a;無論如何修改根目錄下的index.html文件都不會生效 問題原因&#xff1a;在 manifest.json 文件中有個【web配置】—>【index.html模版路徑】&#xff0c;…

C語言第十一章內存在數據中的存儲

一.整數在內存中的存儲在計算機內存中&#xff0c;所有的數字都是以二進制來存儲的。整數也不例外&#xff0c;在計算機內存中&#xff0c;整數往往以補碼的形式來存儲數據。這是為什么呢&#xff1f;在早期計算機表示整數時&#xff0c;最高位為符號位。但是0卻有兩種表示形式…

K8s部署dashboard平臺和基本使用

Kubernetes 的默認 Dashboard 主要用于基本的資源查看與管理,如查看 Pod、Service 等資源的狀態,進行簡單的創建、刪除操作 。然而,在企業級復雜場景下,其功能顯得較為局限。 與之相比,開源的 Kubernetes Dashboard 增強版工具 ——Dashboard UI ,為用戶帶來了更強大的功…

JavaEE進階-文件操作與IO流核心指南

文章目錄JavaEE進階文件操作與IO流核心指南前言&#xff1a;為什么需要文件操作&#xff1f;一、java.io.File 類的基本用法1.1 文件路徑1.2 常用方法示例獲取文件信息創建和刪除文件目錄操作文件重命名和移動二、IO流的基本概念2.1 核心困境&#xff1a;字節流 vs. 字符流字節…