前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >小白也能看懂的基数排序!!!

小白也能看懂的基数排序!!!

作者头像
大忽悠爱学习
发布2021-11-15 10:19:07
3840
发布2021-11-15 10:19:07
举报
文章被收录于专栏:c++与qt学习

基数排序介绍:

基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort)或bin sort,它是通过键值的各个位的值,将要排序的元素分配至某些“桶”中,达到排序的作用 基数排序法是属于稳定性的排序,基数排序法是效率高的稳定性排序法。 基数排序(Radix Sort)是桶排序的扩展,它是这样实现的:将整数按位数切割成不同的数字,然后按每个位数分别比较。

基数排序图解过程

基数排序具体思想

  • 将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。

下面举例说明:

  • 将数组 {53, 3, 542, 748, 14, 214} 使用基数排序, 进行升序排序。
  • 第1轮排序 [按照个位排序]: 说明: 事先准备10个数组(10个桶), 0-9 分别对应 位数的 0-9 (1) 将 各个数,按照个位大小 放入到 对应的 各个数组中 (2) 然后从 0-9 个数组/桶中依次按照加入元素的先后顺序取出 第1轮排序后:542 53 3 14 214 748
  • 第2轮排序 [按照十位排序] (1) 将 各个数,按照十位大小 放入到 对应的 各个数组中 (2) 然后从 0-9 个数组/桶中依次按照加入元素的先后顺序取出 第2轮排序后: 3 14 214 542 748 53
  • 第3轮排序 [按照百位排序] (1) 将 各个数,按照百位大小 放入到 对应的 各个数组中 (2) 然后从 0-9 个数组/桶中依次按照加入元素的先后顺序取出 第3轮排序后:3 14 53 214 542 748 (得到了我们要的顺序)

代码演示

代码语言:javascript
复制
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
using namespace std;
void radixSort(int arr[],int len)
{
	//先求出数组中最大的数
	int max = arr[0];
	for (int i = 0; i < len; i++)
	{
		if (max < arr[i])
			max = arr[i];
	}
	//计算最大的数是几位数
	int maxlen = (int)(log10(max)) + 1;
	//定义一个二维数组,表示十个桶,每个桶的就是一个数组
    //未了防止数据溢出,每个桶的最大长度为len,即所有元素都放入一个桶中
	int* bucket[10];
	for (int i = 0; i < 10; i++)
	{
		bucket[i] = new int[len];
	}
	//定义一个一维数组来记录各个桶每一次放入数据的个数
	int bucketNumCount[10] = { 0 };
	//第一轮:针对每个元素的个位进行排序处理
	for (int i = 0; i < len; i++)
	{
		//取出每个元素的个位进行处理
		int digitOfElement = arr[i] / 1 % 10;
		//放入到个位对应的桶中
		bucket[digitOfElement][bucketNumCount[digitOfElement]] = arr[i];
		//对应桶内个数加一
		bucketNumCount[digitOfElement]++;
	}
	//按照一维数组下标,即桶的顺序,依此取出数据,放入原来的数组中
	int index = 0;
	//遍历每一个桶,将每一个桶中数据放入到原数组中
	for (int i = 0; i < 10; i++)
	{
		//如果第i个桶中有元素就放,否则不放
		if (bucketNumCount[i] != 0)
		{
			//将第i个桶中元素全部倒出来
			for (int j = 0; j < bucketNumCount[i]; j++)
			{
				arr[index++] = bucket[i][j];
			}
		}
		//最后因为当前桶内元素全部倒出,要置空
		bucketNumCount[i] = 0;
	}
	//打印
	cout << "个位排序后:" << endl;
	for_each(arr, arr + 6, [](int val) {cout << val << " "; });
	cout << endl;

	//第二轮:针对每个元素的十位进行排序处理
	for (int i = 0; i < len; i++)
	{
		//取出每个元素的十位进行排序处理
		int digitOfElement = arr[i] / 10 % 10;
		//放入到对应的桶中
		bucket[digitOfElement][bucketNumCount[digitOfElement]] = arr[i];
		//对应桶中的数量加一
		bucketNumCount[digitOfElement]++;
	}
	//按照一维数组下标,即桶的顺序,依此取出数据,放入原来的数组中
	 index = 0;
	//遍历每一个桶,将每一个桶中数据放入到原数组中
	for (int i = 0; i < 10; i++)
	{
		//如果当前第i个桶中存在元素才倒出
		if (bucketNumCount[i] != 0)
		{
			//第i个桶中存在元素,将桶中所有元素倒出来,挨个放入数组中
			for (int j = 0; j < bucketNumCount[i]; j++)
			{
				arr[index++] = bucket[i][j];
			}
		}
		//当前第i个桶倒完后,将桶内元素个数为0
		bucketNumCount[i] = 0;
	}
	//打印
	cout << "十位排序后:" << endl;
	for_each(arr, arr + 6, [](int val) {cout << val << " "; });
	cout << endl;


	//第三轮:针对每个元素的百位进行排序处理
	for (int i = 0; i < len; i++)
	{
		//取出数组中每个元素的百位放入对应桶内
		int digitOfElement = arr[i] / 100 % 10;
		bucket[digitOfElement][bucketNumCount[digitOfElement]] = arr[i];
		//对应桶中元素个数加一
		bucketNumCount[digitOfElement]++;
	}
	//按照一维数组下标,即桶的顺序,依此取出数据,放入原来的数组中
	index = 0;
	//将桶内的元素以此倒回数组
	for (int i = 0; i < 10; i++)
	{
		if (bucketNumCount[i] != 0)
		{
			for (int j = 0; j < bucketNumCount[i]; j++)
			{
				arr[index++] = bucket[i][j];
			}
		}
		bucketNumCount[i] = 0;
	}
	//打印
	cout << "百位排序后:" << endl;
	for_each(arr, arr + 6, [](int val) {cout << val << " "; });
	cout << endl;
}
void test()
{
	int arr[6] = { 53, 3, 542, 748, 14, 214 };
	radixSort(arr, 6);
	cout << "最终排序结果:" << endl;
	for_each(arr, arr + 6, [](int val) {cout << val << " "; });
	cout << endl;
}
int main()
{
	test();
	system("pause");
	return 0;
}

上面这个例子中没有用到我们定义的maxlen这个变量,是因为为了给大家演示排序过程。 下面给出简化版本,即用上maxlen这个变量:

代码语言:javascript
复制
#include<iostream>
#include<algorithm>
#include<cmath>
#include<string>
using namespace std;
void radixSort(int arr[],int len)
{
	//先求出数组中最大的数
	int max = arr[0];
	for (int i = 0; i < len; i++)
	{
		if (max < arr[i])
			max = arr[i];
	}
	//计算最大的数是几位数
	int maxlen = (int)(log10(max)) + 1;
	//定义一个二维数组,表示十个桶,每个桶的就是一个数组
    //未了防止数据溢出,每个桶的最大长度为len,即所有元素都放入一个桶中
	int* bucket[10];
	for (int i = 0; i < 10; i++)
	{
		bucket[i] = new int[len];
	}
	//定义一个一维数组来记录各个桶每一次放入数据的个数
	int bucketNumCount[10] = { 0 };
	
    //最外层for循环负责对每一位数字都进行一次归桶排序拿出操作
	for (int i = 0,n=1; i < maxlen; i++,n*=10)
	{
		//对当前数组每个元素的当前位的数字进行入桶操作
		for (int j = 0; j < len; j++)
		{
			int digNum = arr[j] / n % 10;//获取当前元素指定位数字
			//放入对应桶
			bucket[digNum][bucketNumCount[digNum]] = arr[j];
			//对应桶中的元素个数加一
			bucketNumCount[digNum]++;
		}
		//挨个取出桶中元素放入原来数组中
		int index = 0;
		//遍历每个桶,将桶中元素放入到原数组
		for (int i = 0; i < 10; i++)
		{
			//如果当前桶内元素个数不为0,就全部倒出来
			if (bucketNumCount[i] != 0)
			{
				for (int j = 0; j < bucketNumCount[i]; j++)
				{
					arr[index++] = bucket[i][j];//将第i个桶中的元素依次倒出
				}
			}
			//当前桶内元素清空
			bucketNumCount[i] = 0;
		}
	}

}
void test()
{
	int arr[6] = { 53, 3, 542, 748, 14, 214 };
	radixSort(arr, 6);
	cout << "最终排序结果:" << endl;
	for_each(arr, arr + 6, [](int val) {cout << val << " "; });
	cout << endl;
}
int main()
{
	test();
	system("pause");
	return 0;
}

计算整数位数的三种方法:

代码语言:javascript
复制
	//法1:
	int max=5000;
	char str[100];
	sprintf_s(str,"%d", max);
	int maxlen = strlen(str);
代码语言:javascript
复制
	//法2:
	int max=5000;
	int maxlen = 0;
	while (max > 0)
	{
		max /= 10;
		maxlen++;
	}
	cout << maxlen << endl;
代码语言:javascript
复制
    int max=1000;
	int maxlen = (int)(log10(max)) + 1;
	cout << maxlen << endl;

完结撒花!!!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/04/12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基数排序介绍:
  • 基数排序图解过程
  • 基数排序具体思想
  • 代码演示
  • 完结撒花!!!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档