【數據結構初階】--排序(五)--計數排序,排序算法復雜度對比和穩定性分析

🔥個人主頁:@草莓熊Lotso

🎬作者簡介:C++研發方向學習者

📖個人專欄:?《C語言》?《數據結構與算法》《C語言刷題集》《Leetcode刷題指南》

??人生格言:生活是默默的堅持,毅力是永久的享受。

前言:今天這篇文章主要是想給大家分享一下計數排序,并且對前面實現過的排序算法的時間復雜度,空間復雜度,穩定性進行一個歸納總結。話不多說,我們直接進入正文內容。


目錄

一.計數排序

核心步驟:

代碼實現:

計數排序的特性:?

?二.排序算法復雜度及穩定性分析

各排序算法對比表:?


一.計數排序

計數排序(Counting Sort)又稱為鴿巢原理,是一種非比較型的線性時間排序算法,適用于 輸入數據范圍明確且較窄的場景。核心思想是通過“統計每個值的出現次數”,直接確定元素的最終位置,跳過耗時的比較操作。


核心步驟:

1. 確定數據范圍
遍歷數組,找到最大值 max 和最小值 min,計算數據范圍 range = max - min + 1。
(目的:創建合適大小的計數數組,避免空間浪費)

2. 統計元素出現次數
創建計數數組 count(長度為 range),注意count數組的初始化(開辟時用calloc或者后續用memset),遍歷原數組,將每個元素 arr[i] 映射到 count[arr[i] - min](減去 min 是為了處理包含負數的情況,一定要用arr[i]-min),統計每個值的出現次數。

3. 將count數組中的數據排序還原到原數組中

定義一個索引變量index,用于記錄原數組arr中即將寫入數據的位置。遍歷count數組(從0開始,然后小于<range),根據count[i]統計到的個數進行循環,循環次數等于該值出現的次數,將數組的原始數據值放入arr原始數組中(對應原始值一定是i+min)


代碼實現:

//非比較排序--計數排序
void CountSort(int* arr, int n)
{//找最大最小值確定范圍int min = arr[0]; int max = arr[0];for (int i = 0; i < n; i++){if (arr[i] < min){min = arr[i];}if (arr[i] > max){max = arr[i];}}int range = max - min + 1;int* count = (int*)malloc(sizeof(int) * range);if (count == NULL){perror("malloc fail!");exit(-1);}//對count初始化,可以用memset也可以前面申請空間的時候使用callocmemset(count, 0, sizeof(int) * range);//統計次數,映射,下標為arr[i]-minfor (int i = 0; i < n; i++){count[arr[i] - min]++;}//排序int index = 0;//用range就可以了for (int i = 0; i < range; i++){while (count[i]--){arr[index++] = i + min;//這里需要用i+min}}
}

test.c:

#include"Sort.h"void PrintArr(int* arr, int n)
{for (int i = 0; i < n; i++){printf("%d ", arr[i]);}printf("\n");
}void test1()
{int a[] = { 5, 3, 9, 6, 2, 4, 7, 1, 8 };int size = sizeof(a) / sizeof(a[0]);printf("排序前:");PrintArr(a, size);//直接插入排序//InsertSort(a, size);//希爾排序//ShellSort(a, size);//直接選擇排序//SelectSort(a, size);//堆排序//HeapSort(a, size);//冒泡排序//BubbleSort(a, size);//快速排序//QuickSort(a, 0, size - 1);//非遞歸快速排序//QuickSortNoare(a, 0, size - 1);//快速排序進階版//QuickSortMore(a, 0, size - 1);//歸并排序//MergeSort(a, size);//非遞歸實現歸并排序//MergeSortNore(a, size);//非比較排序--計數排序CountSort(a, size);printf("排序后:");PrintArr(a, size);
}int main()
{test1();return 0;
}

--測試完成,打印沒有問題,升序排序正確,退出碼為0?

計數排序的特性:?

  • 計數排序在數據范圍集中時,效率很高,但是適用范圍以及場景有限。
  • 時間復雜度:O(n+range)
  • 空間復雜度:O(range)
  • 穩定性:穩定

?二.排序算法復雜度及穩定性分析

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

各排序算法對比表:?

--其中冒泡排序,直接插入排序,歸并排序是穩定的,這里就不過多介紹了,我們主要通過一些特例來看下那些不穩定的排序算法。至于時間復雜度和空間復雜度,博主大部分都在前面的博客中分享過了。

1.直接選擇排序:

2.希爾排序:

3.堆排序:

4.快速排序:

--前面一直沒給大家展示過Sort.h文件,在這里給大家看一看

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>//插入排序
//1)直接插入排序
void InsertSort(int* arr, int n);
//2)希爾排序
void ShellSort(int* arr, int n);//選擇排序
//1)直接選擇排序
void SelectSort(int* arr, int n);
//2)堆排序
void HeapSort(int* arr, int n);//交換排序
//1)冒泡排序
void BubbleSort(int* arr, int n);
//2)快速排序
void QuickSort(int* arr, int left, int right);
//快速排序非遞歸版本
void QuickSortNoare(int* arr, int left, int right);
//快速排序進階版本
void QuickSortMore(int* arr, int left, int right);//歸并排序--主函數里面不遞歸,所以可以先不傳left和right
void MergeSort(int* arr, int n);
//非遞歸實現歸并排序
void MergeSortNore(int* arr, int n);//非比較排序--計數排序
void CountSort(int* arr, int n);

往期回顧:

【數據結構初階】--排序(一):直接插入排序,希爾排序

【數據結構初階】--排序(二)--直接選擇排序,堆排序

【數據結構初階】--排序(三):冒泡排序,快速排序

【數據結構初階】--排序(四):歸并排序

結語:本篇博客就到此結束了,后續應該還會更新一篇歸并排序的進階,然后就正式進入C++的學習了。我們數據結構初階講這些數據結構都是用C語言實現的,還有些比較難的數據結構在后續C++的學習中我們也會接觸到,但是利用C++來實現就方便很多了,如果文章對你有幫助的話,歡迎評論,點贊,收藏加關注,感謝大家的支持。

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

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

相關文章

InfluxDB 數據備份與恢復高級策略(二)

案例實戰&#xff1a;InfluxDB 數據備份恢復業務場景描述假設我們正在參與一個大型的物聯網項目&#xff0c;該項目涉及分布在不同區域的數千個傳感器設備 &#xff0c;這些設備實時采集環境溫度、濕度、設備運行狀態等數據&#xff0c;并將這些數據存儲在 InfluxDB 數據庫中。…

sqli-labs通關筆記-第36關GET寬字符注入(單引號閉合 手工注入+腳本注入 3種方法)

目錄 一、轉義函數 1、mysqli_real_escape_string 2、addslashes 3、轉義區別 二、寬字符注入 三、sqlmap之tamper 四、sqlmap之unmagicquotes 五、源碼分析 1、代碼審計 2、SQL注入安全性分析 六、滲透實戰 1、進入靶場 2、id1探測 3、id-1探測 4、id1%df and…

手撕設計模式——咖啡點單系統之裝飾模式

手撕設計模式——咖啡點單系統之裝飾模式 1.業務需求 ? 大家好&#xff0c;我是菠菜啊&#xff0c;好久不見&#xff0c;今天給大家帶來的是——裝飾模式。老規矩&#xff0c;在介紹這期內容前&#xff0c;我們先來看看這樣的需求&#xff1a;現在有一個咖啡館&#xff0c;有…

LRU Cache緩存替換算法

目錄 一、LRU 是什么&#xff1f;Cache是什么&#xff1f; 二、LRU Cache的實現 三、源碼 一、LRU 是什么&#xff1f;Cache是什么&#xff1f; LRU 是 "Least Recently Used" 的縮寫&#xff0c;意思是“最近最少使用”。它是一種常用的 緩存&#xff08;Cache&…

自定義視圖:圖形與圖像的處理(二):繪圖

除了使用已有的圖片之外&#xff0c;Android應用還常常需要在運行時動態地生成圖片&#xff0c;比如一個手機游戲&#xff0c;游戲界面看上去豐富多彩&#xff0c;而且可以隨著用戶動作而動態改變&#xff0c;這就需要借助于Android的繪圖支持了。1. Android繪圖基礎:Canvas、P…

微服務、服務網格、Nacos架構與原理

Nacos架構與原理 -服務網格生態-阿里云開發者社區 ------ 該文章用于學習參考,如有侵權,請直接聯系下架 服務網格的核心職責:治理“服務通信” 包括但不限于: 功能 舉例說明 負載均衡 動態選擇服務實例 熔斷、重試 某個服務失敗時自動切換、重試 流量路由 灰度發布、藍綠…

STM32——啟動過程淺析

總&#xff1a;STM32——學習總綱 參考文件&#xff1a; STM32 MAP文件淺析-V1.1 STM32 啟動文件淺析_V1.2 Cortex-M3權威指南(中文)、ARM Cotrex-M3權威指南(英文).zip 一、Map文件解析 1.1 MDK編譯過程文件 在編譯中&#xff0c;會生成11種編譯過程文件&#xff0c;可…

區塊鏈簡介

一、區塊鏈簡介 狹義上的定義&#xff1a; 區塊鏈是一種鏈式數據結構&#xff0c;通過按時間順序將數據塊逐一連接形成。這種結構通過密碼學確保了數據的不可篡改性和不可偽造性&#xff0c;形成了一種分布式賬本技術。 廣義上的定義&#xff1a; 區塊鏈技術不僅僅是一種數據…

NestJS中@Injectable裝飾器

一、基礎定義與核心作用 1.1 什么是Injectable&#xff1f; Injectable() 是 NestJS 依賴注入&#xff08;Dependency Injection, DI&#xff09;系統的核心裝飾器&#xff0c;用于將類標記為可注入的提供者&#xff08;Provider&#xff09;。它告知 NestJS 的 IoC&#xff08…

【機器學習深度學習】大模型應用落地:微調與RAG的角色與實踐

目錄 前言 一、微調與RAG&#xff1a;大模型應用落地的兩大支柱 1. 微調&#xff08;Fine-tuning&#xff09; 2. RAG&#xff08;Retrieval-Augmented Generation&#xff09; 二、微調可以做什么&#xff1f; 1. 模型自我認知調整 2. 對話風格優化 3. 提升問題理解能…

List、ArrayList 與順序表

目錄 一、List 介紹 二、線性表 三、自己實現 ArrayList 3.1 顯示元素 3.2 增 3.2.1 默認在數組后面新增元素 3.2.2 在指定位置中新增元素 3.3 查 3.4 取值 3.5 改 3.5.1 把 pos 位置的元素修改成 value 3.5.2 刪除某個元素 3.5.3 清空 四、認識 ArrayList 4.0 說…

Baumer工業相機堡盟工業相機如何通過YoloV8深度學習模型實現各類垃圾的分類檢測識別(C#代碼UI界面版)

Baumer工業相機堡盟工業相機如何通過YoloV8深度學習模型實現各類垃圾的分類檢測識別&#xff08;C#代碼UI界面版&#xff09;工業相機使用YoloV8模型實現各類垃圾的分類檢測識別工業相機通過YoloV8模型實現各類垃圾的分類檢測識別的技術背景在相機SDK中獲取圖像轉換圖像的代碼分…

EasyExcel高效工具類:簡化Excel導入導出,支持多Sheet與枚舉轉換

文章目錄前言一、依賴坐標二、工具類&#xff1a;ExcelUtil三、測試1.實體類2.前置操作3.單Sheet導出4.單Sheet導入5.多Sheet導出6.多Sheet導入7.完整代碼四、擴展&#xff1a;自定義注解實現枚舉類型轉換1.枚舉接口2.枚舉類3.注解4.轉換類5.使用示例6.測試總結前言 在現代應用…

技術速遞|GitHub Copilot for Eclipse 邁出重要一步

我們非常高興地宣布&#xff1a;2025 年 7 月 22 日&#xff0c;GitHub Copilot for Eclipse 又邁出了重要一步&#xff0c;Eclipse 變得更智能、更快捷&#xff0c;而且與 Eclipse 的集成也更無縫了&#xff01;這是繼新功能上線以來&#xff0c;又一次質的提升。 &#x1f…

Coze Loop:開源智能體自動化流程編排平臺原理與實踐

項目簡介 Coze Loop 是 Coze 團隊開源的智能體自動化流程編排平臺。它以“Loop”為核心概念,支持開發者通過低代碼/可視化方式,將多種 AI Agent、插件、API、數據流等靈活編排為自動化工作流,實現復雜的智能體協作、任務自動化和多模態數據處理。Coze Loop 適用于企業自動化…

[GESP202309 四級] 2023年9月GESP C++四級上機題題解,附帶講解視頻!

本文為2023年9月GESP C四級的上機題目的詳細題解&#xff01;覺得寫的不錯或者有幫助可以點個贊啦。 目錄 題目一講解視頻: 題目二講解視頻: 題目一:進制轉換 解題思路: 代碼(C): 題目二:變長編碼 解題思路: 代碼(C): 題目一講解視頻: 2023年9月GESP C四級上機題一題目…

【AI編程工具IDE/CLI/插件專欄】-國外IDE與Cursor能力對比

AI編程專欄(二) - Cursor 深度使用指南 Cursor 深度使用指南(二) - 新能力使用教程 從Trae 2.0與CodeBuddy IDE發布&#xff0c;談大廠布局IDE 如何選擇AI IDE&#xff1f;對比Cursor分析功能差異 AI編程工具IDE/CLI/插件專欄-熱門AI編程CLI初識與IDE對 前面文章介紹過了國…

word2vector細致分解(CBOW, SKIP_GRAM, 層次soft Max, 負采樣)

1 前世今生&#xff1a;NGRAM NGRAM&#xff1a;將詞當成一個離散的單元&#xff08;因此存在一定的局限性&#xff0c;沒有考慮到詞與詞之間的關系&#xff09; neural network language model&#xff1a;只能處理定長序列&#xff0c;訓練慢。使用RNN之后有所改善 2 兩種訓…

Elasticsearch向量庫

在Elasticsearch&#xff08;ES&#xff09;最新版本&#xff08;目前8.x系列&#xff09;中&#xff0c;無需額外的“embedding插件”&#xff0c;因為ES從7.14版本開始就原生支持向量數據類型&#xff08;dense_vector&#xff09; 和向量搜索能力&#xff0c;可直接作為向量…

嵌入式學習的第四十四天-ARM

一、ARM內核基礎知識1.ALU算術邏輯單元&#xff1b;完成運算的電路2.通用寄存器&#xff1a;R0~R15R13&#xff08;SP&#xff09;&#xff1a;棧指針寄存器&#xff1a;指向棧的指針&#xff08;指向正確的位置&#xff09;&#xff0c;為了保護現場 R14&#xff08;LR…