惊叹数据结构之美,品味排序算法之妙:对计排、桶排的详细介绍

惊叹数据结构之美,品味排序算法之妙:对计排、桶排的详细介绍
大家好,这里是小编的博客频道
小编的博客:就爱学编程
很高兴在ZEEKLOG这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!!

本文目录


引言

排序算法中的基数排序和计数排序都是非基于传统比较的排序方法,它们各自有着独特的实现原理和应用场景。下面小编将从代码实现的角度对这两种排序算法进行详细介绍。

在这里插入图片描述

那接下来就让我们开始遨游在知识的海洋!

正文


一、计数排序(Counting Sort)

原理概述

计数排序是一种适用于元素范围较小的排序算法。它利用一个额外的计数数组来记录待排序数组中每个元素出现的次数,然后根据这些次数来确定每个元素在最终排序数组中的位置。

代码实现步骤

1. 确定元素范围:找出待排序数组中的最小值和最大值,记为min和max。2. 创建计数数组:创建一个大小为max-min+1的计数数组count,用于记录每个元素出现的次数。数组的下标代表元素的值,数组的值代表该元素出现的次数。3. 统计频次:遍历待排序数组,统计每个元素出现的频率,并将该频率存储到计数数组中。4. 累计计数:将计数数组中的值进行累加,得到每个元素在最终排序数组中的位置。这个步骤确保了排序的稳定性(即相同元素的相对位置不变)。5. 构造排序结果:根据累加后的计数数组,将元素按顺序放入目标排序数组中。

示例代码

#include<iostream>usingnamespace std;int*count_sort(int* input,int len,int min,int max){int* arr =newint[max - min +1];// 创建计数数组for(int i =0; i < max - min +1; i++) arr[i]=0;// 初始化计数数组为0// 统计每个元素的出现次数for(int i =0; i < len; i++){ arr[input[i]- min]++;}int* ans =newint[len];// 创建目标排序数组int index =0;// 用于填充目标排序数组的索引// 根据计数数组构建目标排序数组for(int i = min; i <= max; i++){for(int j =0; j < arr[i - min]; j++){ ans[index++]= i;}}return ans;// 返回排序后的数组}intmain(){int arr[]={3,6,4,5,6,3,6,4,5,5,6,4,3};int len =sizeof(arr)/sizeof(int);int* sorted_arr =count_sort(arr, len,3,6);// 输出排序结果for(int i =0; i < len; i++){ cout << sorted_arr[i]<<" ";} cout << endl;delete[] sorted_arr;// 释放动态分配的内存return0;}

二、基数排序(Radix Sort)

原理概述

基数排序又称桶排序,它通过将所有数字分配到应在的位置最后再覆盖到原数组完成排序的过程。基数排序分为最高位优先法(MSD)和最低位优先法(LSD)。这里以最低位优先法为例进行说明。
基数排序的基本思想是从数字的最低有效位开始,依次对每个数位进行一次排序。每次排序都使用稳定的排序算法(如计数排序),以保证排序后元素的相对位置不变。经过多次排序后,整个数列就变得有序了。

代码实现步骤

1. 获取最大位数:找出待排序数组中所有数字的最大位数。2. 逐位排序:从最低有效位开始,依次对每个数位进行排序。每次排序都使用计数排序算法。3. 合并结果:由于每次排序都是稳定的,所以可以直接在原数组上进行操作,无需额外的合并步骤。

示例代码(以最低位优先法为例):

#include<iostream>#include<vector>#include<algorithm>#include<cmath>usingnamespace std;// 获取数字d在第pos位的值(0~9)intgetDigit(int d,int pos){return(d /static_cast<int>(pow(10, pos)))%10;}// 对数组arr按照第pos位进行计数排序voidcountingSortByDigit(vector<int>& arr,int pos){constint radix =10;// 基数为10(因为是十进制数) vector<int>output(arr.size());// 存储排序结果的数组 vector<int>count(radix,0);// 计数数组// 统计每个数字在第pos位上出现的次数for(int num : arr){int digit =getDigit(num, pos); count[digit]++;}// 修改count数组,使其包含实际位置信息for(int i =1; i < radix; i++){ count[i]+= count[i -1];}// 构建输出数组for(int i = arr.size()-1; i >=0; i--){int digit =getDigit(arr[i], pos); output[count[digit]-1]= arr[i]; count[digit]--;}// 将排序结果复制回原数组copy(output.begin(), output.end(), arr.begin());}// 基数排序主函数voidradixSort(vector<int>& arr){if(arr.empty())return;// 找到最大数的位数int maxNum =*max_element(arr.begin(), arr.end());int maxDigits =log10(maxNum)+1;// 从个位开始,逐位进行计数排序for(int pos =0; pos < maxDigits; pos++){countingSortByDigit(arr, pos);}}intmain(){ vector<int> arr ={170,45,75,90,802,24,2,66};radixSort(arr);// 输出排序结果for(int num : arr){ cout << num <<" ";} cout << endl;return0;}

三、总结

  • 计数排序:适用于元素范围较小的情况,时间复杂度为O(n+k),其中n是待排序元素的个数,k是元素的范围。空间复杂度高,需要额外的计数数组。
  • 基数排序:通过逐位排序来实现整体排序,通常使用计数排序作为子过程。时间复杂度为O(d*(n+r)),其中d是数字的最大位数,n是待排序元素的个数,r是基数(对于十进制数,r=10)。基数排序是稳定的排序算法。

快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!

Read more

Qt步进电机上位机控制程序源代码:跨平台C/C++编写,支持多种端口类型与详细注释

Qt步进电机上位机控制程序源代码:跨平台C/C++编写,支持多种端口类型与详细注释

Qt步进电机上位机控制程序源代码Qt跨平台C/C++语言编写 支持串口Tcp网口Udp网络三种端口类型 提供,提供详细注释和人工讲解 1.功能介绍: 可控制步进电机的上位机程序源代码,基于Qt库,采用C/C++语言编写。 支持串口、Tcp网口、Udp网络三种端口类型,带有调试显示窗口,接收数据可实时显示。 带有配置自动保存功能,用户的配置数据会自动存储,带有超时提醒功能,如果不回复则弹框提示。 其中三个端口,采用了类的继承与派生方式编写,对外统一接口,实现多态功能,具备较强的移植性。 2.环境说明: 开发环境是Qt5.10.1,使用Qt自带的QSerialPort,使用网络的Socket编程。 源代码中包含详细注释,使用说明,设计文档等。 请将源码放到纯英文路径下再编译。 3.使用介绍: 可直接运行在可执行程序里的exe文件,操作并了解软件运行流程。 本代码产品特点: 1、尽量贴合实际应用,细节考虑周到。 2、注释完善,讲解详细,还有相关扩展知识点介绍。

By Ne0inhk
redis学习笔记(八)—— C++ 操作 Redis

redis学习笔记(八)—— C++ 操作 Redis

redis-plus-plus 库 C++ 操作 Redis 的库有很多,这里使用 redis-plus-plus 库 Github 地址: https://github.com/sewenew/redis-plus-plus 安装 hiredis redis-plus-plus 是基于 hiredis 实现的(hiredis 是一个 C语言实现的 redis 客户端) aptinstall libhiredis-dev # Ubuntu yum install hiredis-devel.x86_64 # Centos 下载 redis-plus-plus 源码 git clone https://github.com/sewenew/redis-plus-plus.git 编译安装 redis-plus-plus Ubuntu

By Ne0inhk
【C++初阶】:C++入门相关知识(3):引用 & inline内联函数 & nullptr相关概念

【C++初阶】:C++入门相关知识(3):引用 & inline内联函数 & nullptr相关概念

🎈主页传送门:良木生香 🔥个人专栏:《C语言》 《数据结构-初阶》 《程序设计》《鼠鼠的C++学习之路》 🌟人为善,福随未至,祸已远行;人为恶,祸虽未至,福已远离 前言:在上一篇文章中,我们学习了C++的输入输出,缺省参数以及函数重载,这些都是C++入门必备的基础知识,那么在这篇文章中,我们就要来学习剩下C++其他的基础知识,那就是引用、inline、以及nullptr这些知识。 一、引用 1.1、引用的概念和定义 引用不是定义一个新变量,而是给已经存在的变量起一个别名,那么编译器就不会为别名重新开辟空间,它和引用变量共同使用同一块空间。就好比我们把土豆称为马铃薯,番茄称为西红柿一样,都是取了一个新的别名,但是东西是同一个东西,所以引用的语法如下: 类型& 别名 = 变量 使用方法如下: int a = 10; int&

By Ne0inhk