C语言实现桶排序(基数排序)

本文详细介绍了如何使用桶排序算法对整数数组进行排序,通过逐个位数划分桶并动态调整计数,简化了代码管理,提高了空间效率。实例演示了针对数组arr={32,33,23,42,12,54,53,52,100}

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

桶排序是一种神奇的算法。

问题:

假设有数组:arr[] = { 32, 33, 23, 42, 12, 54, 53, 52, 100 };

该如何用桶排序?

第一轮:

  1. 准备十个桶子
  2. 从前向后遍历,将个位为x的数字依次放入第x个桶子中,即:

    桶0:100

    桶1:

    桶2:32, 42, 12, 52

    桶3:33, 23, 53

    桶4:54

    桶5:

    ……

  3. 将所有桶中元素依次倒出至原数组:arr[] = { 100, 32, 42, 12, 52, 33, 23, 53, 54 };

第二轮:

  1. 从前向后遍历,将十位为x的数字依次放入第x个桶子中,即:

    桶0:100

    桶1:12

    桶2:23

    桶3:32, 33

    桶4:42

    桶5:52, 53, 54

    ……

  2. 将所有桶中元素依次倒出至原数组:arr[] = { 100, 12, 23, 32, 33, 42, 52, 53, 54 }

第三轮:

  1. 从前向后遍历,将百位为x的数字依次放入第x个桶子中,即:

    桶0:12, 23, 32, 33, 42, 52, 53, 54

    桶1:100

    桶2:

    ……

  2. 将所有桶中元素依次倒出至原数组:arr[] = { 12, 23, 32, 33, 42, 52, 53, 54, 100 }

实现:

具体实现稍有区别

  • 如果对于给出的数组arr而言,为了使代码简洁易于管理,不应该分别创建十个桶,分别装每一个数字,那样会使代码冗余且难以管理,空间复杂度上升,所以我们采用遍历数组记录数组中数字的 个位/十位/百位 的个数,再并从后向前遍历,将对应的元素放入本次桶装后倒出后元素该存在的位置。
  • 动态分配一个pa空间,其大小为传入数组的大小,专门用来存放每次排序后的数组。

int *pa = (int*)malloc(size * sizeof(int));

  • 创建一个count[10]数组,下标的位置专门用来存放该桶应该放入的数字个数,比如:

上面的例子中:arr[] = { 32, 33, 23, 42, 12, 54, 53, 52, 100 }; (size == 9)

则个位数入桶时:count = { 1, 0, 4, 3, 1, 0, 0, 0, 0, 0 };

对这个数组稍加变动,变为每次count中某一位 ++ 时,后面的每一位都++,则:

  • 表示:每次下标位变动时第[n]位的值,即第n桶内最后一个元素在数组中所排的位置。

个位为例:

桶0:100                        //存一个数字

桶1:

桶2:32, 42, 12, 52        //存四个数字

桶3:33, 23, 53              //存三个数字

桶4:54                          //存一个数字

桶5:

……

从后向前遍历时,检查每个个位的数字:

  • 遇到100,将它放在数组中第 count[0] - 1 == 0位,且count[0]-- == 0

此时pa == {100, 0, 0, 0, 0, 0, 0, 0, 0 };    count[] == { 1, 1, 5, 8, 9, 9, 9, 9, 9, 9 };

  • 遇到52,将它放在数组中第 count[2] - 1 == 4位,且count[2]-- == 4

此时pa == {100, 0, 0, 0, 52, 0, 0, 0, 0 };    count[] == { 1, 1, 4, 8, 9, 9, 9, 9, 9, 9 };

  • 遇到53,将它放在数组中第 count[3] - 1 == 7位,且count[3]-- == 7

此时pa == {100, 0, 0, 0, 52, 0, 0, 53, 0 };    count[] == { 1, 1, 4, 7, 9, 9, 9, 9, 9, 9 };

  • 遇到54,将它放在数组中第 count[4] - 1 == 8位,且count[4]-- == 8

此时pa == {100, 0, 0, 0, 52, 0, 0, 53, 54 };    count[] == { 1, 1, 4, 7, 8, 9, 9, 9, 9, 9 };

  • 遇到12,将它放在数组中第 count[2] - 1 == 3位,且count[2]-- == 3

此时pa == {100, 0, 0, 12, 52, 0, 0, 53, 54 };    count[] == { 1, 1, 3, 7, 8, 9, 9, 9, 9, 9 };

  • 遇到42,将它放在数组中第 count[2] - 1 == 2位,且count[2]-- == 2

此时pa == {100, 0, 42, 12, 52, 0, 0, 53, 54 };    count[] == { 1, 1, 2, 7, 8, 9, 9, 9, 9, 9 };

  • 遇到23,将它放在数组中第 count[3] - 1 == 6位,且count[3]-- == 6

此时pa == {100, 0, 42, 12, 52, 0, 23, 53, 54 };    count[] == { 1, 1, 2, 6, 8, 9, 9, 9, 9, 9 };

  • 遇到33,将它放在数组中第 count[3] - 1 == 5位,且count[3]-- == 5

此时pa == {100, 0, 42, 12, 52, 33, 23, 53, 54 };    count[] == { 1, 1, 2, 5, 8, 9, 9, 9, 9, 9 };

  • 遇到32,将它放在数组中第 count[2] - 1 == 1位,且count[2]-- == 1

此时pa == {100, 32, 42, 12, 52, 33, 23, 53, 54 };    count[] == { 1, 1, 1, 5, 8, 9, 9, 9, 9, 9 };

这样我们就可以通过从后向前遍历的方式来判断每个数字入桶时的位置。

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <math.h>
#include <memory.h>
#include <stdlib.h> 
#include <malloc.h>

//桶排序
void RadixSort(int *arr, int size)
{
	int *pa = (int*)malloc(size * sizeof(int));
	memset(pa, 0, size * sizeof(int));

	int count[10] = { 0 };
	int boundary = 0;
	int temp = 0;
	int i = 0;

	//最大值
	for (i = 0; i < size; i++)
	{
		boundary = abs(arr[i]) > abs(boundary) ? arr[i] : boundary;
	}

	//求最大数字的十进制位数
	i = 0;
	while (boundary)
	{
		i += boundary? 1 : 0;
		boundary /= 10;
	}
	boundary = i;

	for (i = 0; i < boundary; i++)
	{
		int j = 0;
		
        //标号统计
		for (j = 0; j < size; j++)
		{
			temp = arr[j] / (int)pow(10, i);
			temp = temp % 10;
			while (temp < 10)
			{
				count[temp++]++;
			}
		}

		//入桶:
		for (j = size - 1; j >= 0; j--)
		{
			temp = arr[j] / (int)pow(10, i);
			temp = temp % 10;
			pa[--count[temp]] = arr[j];
		}

		//出桶:
		memcpy(arr, pa, size * sizeof(int));
        
        //清空:
		memset(pa, 0, size * sizeof(int));
		for (j = 0; j < 10; j++)
		{
			count[j] = 0;
		}
	}

	free(pa);
	pa = NULL;
}

int main()
{
	int arr[] = { 32, 33, 23, 42, 12, 54, 53, 52, 100};
	int size = sizeof(arr) / sizeof(arr[0]);
	RadixSort(arr, size);

	for (int i = 0; i < size; i++)
	{
		printf("%d ", arr[i]);
	}

	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KamikazePilot

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值