当前位置: 首页 > news >正文

c++数据结构算法复习基础--13--基数算法

基数排序 - 桶排序

时间复杂度 O(n*d) – d为数据的长度
在这里插入图片描述

每次比较一位(个位、十位。。。),所以取值范围就为0-9。
根据该特点,设计桶的概念 – 0号桶、1号桶…
在这里插入图片描述

1、思想

1)找出最长的数字,确定要处理的桶的趟数(位数)
2)依次由个位开始处理,把相应位数上的数字,放入相应序号的桶内,
完成后,再按照桶的序号,依次取出桶里面的数据,放回原始数据当中。
3)当处理完所有的位数,最终得到有序的序列。

2、局限性

1)数据类型改变,需要代码较大的修改。
对于之前的代码,如果换成浮点数等其他类型数据,大体代码思路一致。
但是基数算法不行,代码无法做到统一,需要进一步修改。
2)对于数据正负性,要求较高。
之前的代码,数据正负性影响不大,可比较即可。
对于基数排序,需要进一步堆数据进行修改。下文实现的代码,对于负数无法实现。

3、实现过程

在这里插入图片描述
1)从左到右依次遍历原始数据,先由个位开始比较。根据每个数据的个位,放入相应的桶中。一次遍历,如下图所示:
在这里插入图片描述
2)依次遍历各个桶,将其重新拷贝到原数据。
在这里插入图片描述
3)根据十位,依次放入对应桶中。
在这里插入图片描述
4)依次取出数据
在这里插入图片描述
因为此次数据最大为两位数,所以这次操作,就可以发现数据有序了。

4、核心代码:

1)循环每次取出位上的数字。

在这里插入图片描述

2)桶的定义,

需要为二维数组。使用vector<vector<int>>

4、代码实现

#include<iostream>
#include<stdlib.h> //包含随机数函数srand
#include<time.h> //需要用time作为随机数种子
#include<string>
#include<vector>//基数排序代码
void RadixSort(int arr[], int size)
{int maxData = arr[0];//求得数据最大值for (int i = 1; i < size; i++){if (maxData < arr[i]){maxData = arr[i];}}//使用系统自带的函数,求取最大值的位数int len = to_string(maxData).size();//定义桶的二维数组vector<vector<int>> vecs;//这里底层并没有空间int mod = 10;int dev = 1;//处理数据for (int i = 0; i < len; mod *= 10, dev *= 10, i++) //O(d) d为数据的长度{vecs.resize(10);for (int j = 0; j < size; j++){//得到当前元素第i个位置的数字int index = arr[j] % mod / dev;vecs[index].push_back(arr[j]);}//依次遍历所有的桶,把元素拷贝回原始的数组当中int idx = 0;for (auto vec : vecs){for (int v : vec){arr[idx++] = v;}}//清空桶内元素,方便下次使用vecs.clear();}}

测试

int main()
{int arr[10];srand(time(NULL));for (int i = 0; i < 10; i++){arr[i] = rand() % 100 + 1;}for (int v : arr){cout << v << "  ";}cout << endl;RadixSort(arr, sizeof(arr) / sizeof(arr[0]));for (int v : arr){cout << v << "  ";}cout << endl;return 0;
}

在这里插入图片描述

5、 对于有负数情况下,代码修改

1)桶,需要设计为20个。增加负数存放的位置。

vecs.resize(20);

2)求取最大值位数时,需要增加abs() – 绝对值函数

//求得数据最大值
for (int i = 1; i < size; i++)
{if (maxData < abs(arr[i])){maxData = abs(arr[i]);}
}

3) 数据的存放

取得所需位数后,再加10。
负数放于0-9的桶中,正数放于10-19的桶中。

	for (int j = 0; j < size; j++){//得到当前元素第i个位置的数字int index = arr[j] % mod / dev + 10;vecs[index].push_back(arr[j]);}

代码实现

//基数排序代码
void RadixSort(int arr[], int size)
{int maxData = arr[0];//求得数据最大值for (int i = 1; i < size; i++){//为了处理负数,使用abs(),取绝对值if (maxData < abs(arr[i])){maxData = abs(arr[i]);}}//使用系统自带的函数,求取最大值的位数int len = to_string(maxData).size();//定义桶的二维数组vector<vector<int>> vecs;//这里底层并没有空间int mod = 10;int dev = 1;//处理数据for (int i = 0; i < len; mod *= 10, dev *= 10, i++){vecs.resize(20);//20个桶,为了能处理负数 -9 --  9for (int j = 0; j < size; j++){//得到当前元素第i个位置的数字int index = arr[j] % mod / dev + 10;vecs[index].push_back(arr[j]);}//依次遍历所有的桶,把元素拷贝回原始的数组当中int idx = 0;for (auto vec : vecs){for (int v : vec){arr[idx++] = v;}}//清空桶内元素,方便下次使用vecs.clear();}}

测试

在这里插入图片描述

http://www.lryc.cn/news/506025.html

相关文章:

  • ntp设置
  • 如何在Java中使用封装好的API接口?
  • AWS EKS 相关错误修复 - remote error: tls: internal error - CSR pending
  • 浏览器事件循环机制
  • ubuntu22.04编译安装Opencv4.8.0+Opencv-contrib4.8.0教程
  • 概率论得学习和整理27:关于离散的数组 随机变量数组的均值,方差的求法3种公式,思考和细节。
  • 【排序算法】——插入排序
  • MySQL的并发控制与MVCC机制深度解析
  • Qt编译MySQL数据库驱动
  • uniapp地址类 方法
  • 使用Idea自带的git功能进行分支合并
  • 酷盾安全:Edge SCDN边缘安全内容分发网络
  • H5 中 van-popup 的使用以及题目的切换
  • Liinux下VMware Workstation Pro的安装,建议安装最新版本17.61
  • WebRTC服务质量(05)- 重传机制(02) NACK判断丢包
  • 修改ubuntu apt 源及apt 使用
  • 深入解析 `DataFrame.groupby` 和 `agg` 的用法及使用场景
  • MySQL 的锁
  • 二、使用langchain搭建RAG:金融问答机器人--数据清洗和切片
  • 【Linux】-- linux 配置用户免密登录本机
  • 泷羽sec学习打卡-brupsuite8伪造IP和爬虫审计
  • 【uniapp蓝牙】基于native.js链接ble和非ble蓝牙
  • .NET Core 各版本特点、差异及适用场景详解
  • Linux中自动检测并定时关闭KDialog程序
  • CSS学习记录12
  • 【Java基础面试题016】JavaObject类中有什么主要方法,作用是什么?
  • 实践环境-docker安装mysql8.0.40步骤
  • 边缘智能创新应用大赛获奖作品系列一:智能边缘计算✖软硬件一体化,开启全场景效能革命新征程
  • 决策树的生成与剪枝
  • 蓝桥杯算法训练 黑色星期五