排序算法之九 基数排序(C++版本)

一. 实现原理

基数排序的相关知识,参考漫画:什么是基数排序?

二. 具体实现

实现中,使用vector作为桶,只是从编码便利的角度出发。

辅助函数

// 获取data的位数
int GetBitCount(int data)
{
	int curCount = 0;
	while (data != 0)
	{
		++curCount;
		data = data / 10;
	}

	return curCount;
}

// 获取某个数的某一位的值,certainBit 1表示个位,2表示十位,依次类推
int GetDataInBit(int data, int certainBit)
{
	int remainder = 0;
	while (certainBit-- != 0)
	{
		remainder = data % 10;
		data = data / 10;
	}

	return remainder;
}
// 获取数组中元素的最大位数
int GetMaxBitCount(int* pData, int size)
{
	int maxBitCount = 0;
	for (int idx = 0; idx < size; ++idx)
	{
		int curBitCount = GetBitCount(pData[idx]);
		if (curBitCount > maxBitCount) maxBitCount = curBitCount;
	}

	return maxBitCount;
}

最终实现

void RadixSort(int* pData, int size)
{
	if (nullptr == pData || size < 1) return;

	std::vector<std::vector<int>> tempTables(10); // 总共10个桶

	for (int curBit = 1; curBit <= GetMaxBitCount(pData, size); ++curBit) // 从最低为1到最高位maxBitCount
	{
		for (int idx = 0; idx < size; ++idx)// 将各个元素根据当前位的数字分到各个桶
		{
			int curData = GetDataInBit(pData[idx], curBit);
			tempTables[curData].push_back(pData[idx]);
		}

		int curIdx = 0; // 将桶中元素写回到原数组
		for (auto& curTable : tempTables)
		{
			for (int curData : curTable) pData[curIdx++] = curData;
			curTable.clear(); // 清空vector
		}
	}
}

三. 输出验证

加上相关的输出信息后再进行调用。

辅助函数

void Print(int* pData, int size)
{
	for (int idx = 0; idx < size; ++idx) std::cout << pData[idx] << " ";
	std::cout << std::endl;
}

初始数据为

int datas[30] = { 41 167 34 100 269 124 78 258 262 164 5 245 181 27 61 191 295 242 27 36 291 204 2 153 292 82 21 116 218 95 };

输出版本

void RadixSort_Output(int* pData, int size)
{
	if (nullptr == pData || size < 1) return;

	std::vector<std::vector<int>> tempTables(10);  // 总共10个桶

	int maxBitCount = GetMaxBitCount(pData, size);
	for (int curBit = 1; curBit <= maxBitCount; ++curBit) // 从最低为1到最高位maxBitCount
	{
		for (int idx = 0; idx < size; ++idx)// 将各个元素根据当前位的数字分到各个桶
		{
			int curData = GetDataInBit(pData[idx], curBit);
			tempTables[curData].push_back(pData[idx]);
		}

		std::cout << std::endl << "CUR BIT " << curBit << std::endl;

		for (int idx = 0; idx < (int)tempTables.size(); ++idx)
		{
			auto& curTable = tempTables[idx];
			std::cout << std::endl << "BUCKET " << idx << std::endl;
			Print(curTable.data(), (int)curTable.size());
		}

		int curIdx = 0; // 将桶中元素写回到原数组
		for (auto& curTable : tempTables)
		{
			for (int curData : curTable) pData[curIdx++] = curData;
			curTable.clear();
		}

		std::cout << "WRITE BACK " << std::endl;
		Print(pData, size);
	}
}

调用输出

INIT DATA // 初始数据
41 167 34 100 269 124 78 258 262 164 5 245 181 27 61 191 295 242 27 36 291 204 2 153 292 82 21 116 218 95

CUR BIT 1 // 开始按个个位进行分桶

BUCKET 0 // 0号桶
100

BUCKET 1 // 1号桶
41 181 61 191 291 21

BUCKET 2 // 2号桶
262 242 2 292 82

BUCKET 3 // 3号桶
153

BUCKET 4 // 4号桶
34 124 164 204

BUCKET 5 // 5号桶
5 245 295 95

BUCKET 6 // 6号桶
36 116

BUCKET 7 // 7号桶
167 27 27

BUCKET 8 // 8号桶
78 258 218

BUCKET 9 // 9号桶
269

WRITE BACK // 将桶中元素写回到远数组
100 41 181 61 191 291 21 262 242 2 292 82 153 34 124 164 204 5 245 295 95 36 116 167 27 27 78 258 218 269

CUR BIT 2 // 开始按十位进行分桶

BUCKET 0
100 2 204 5

BUCKET 1
116 218

BUCKET 2
21 124 27 27

BUCKET 3
34 36

BUCKET 4
41 242 245

BUCKET 5
153 258

BUCKET 6
61 262 164 167 269

BUCKET 7
78

BUCKET 8
181 82

BUCKET 9
191 291 292 295 95

WRITE BACK
100 2 204 5 116 218 21 124 27 27 34 36 41 242 245 153 258 61 262 164 167 269 78 181 82 191 291 292 295 95

CUR BIT 3 // 开始按百位进行分桶

BUCKET 0
2 5 21 27 27 34 36 41 61 78 82 95

BUCKET 1
100 116 124 153 164 167 181 191

BUCKET 2
204 218 242 245 258 262 269 291 292 295

BUCKET 3


BUCKET 4


BUCKET 5


BUCKET 6


BUCKET 7


BUCKET 8


BUCKET 9


WRITE BACK
2 5 21 27 27 34 36 41 61 78 82 95 100 116 124 153 164 167 181 191 204 218 242 245 258 262 269 291 292 295

FINAL DATA // 最终数据
2 5 21 27 27 34 36 41 61 78 82 95 100 116 124 153 164 167 181 191 204 218 242 245 258 262 269 291 292 295
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值