基数桶排序算法

算法原理

基数 排序 是 箱 排序 的 改进 和 推广。 箱 排序 也称 桶 排序( Bucket Sort), 其 基本 思想 是: 设置 若干个 箱子, 依次 扫描 待 排序 的 记录 R[ 0], R[ 1],…, R[ n- 1], 把 关键字 等于 k 的 记录 全都 装入 到 第 k 个 箱子 里( 分配), 然后 按序 号 依次 将 各 非 空的 箱子 首尾 连接 起来( 收集)。 例如, 要将 一副 混 洗 的 52 张 扑克牌 按 点数 A< 2<…< J< Q< K 排序, 需 设置 13 个“ 箱子”, 排序 时 依次 将 每张 牌 按 点数 放入 相应 的 箱子 里, 然后 依次 将 这些 箱子 首尾相接, 就得 到了 按 点数 递增 顺序 排列 的 一副 牌。 基数 排序 是 基于 多 关键字 的, 什么 是 多 关键字 呢? 如果 文件 中 任何 一个 记录 R[ i] 的 关键字 都由 d 个 分量 构成, 而且 这 d 个 分量 中 每个 分量 都是 一个 独立 的 关键字, 则 文件 是 多 关键字 的( 比如 扑克牌 有 两个 关键字: 点数 和 花色)。 通常 实现 多 关键字 排序 有两 种 方法: 最高 位 优先( Most Significant Digit first, MSD); 最低 位 优先( Least Significant Digit first, LSD)。 基数 排序 是 典型的 LSD 排序 方法, 其 基本 思想 是: 从低 位 到 高位 依次 对数 据 进行 箱 排序。 在 d 趟 箱 排序 中, 所需 的

箱子 数 就是 基数 rd( 可能 的 取值 个数), 这就 是“ 基数 排序” 名称 的 由来。 比如, 对于 值 范围 为 10 ~ 99 的 整数 序列: 45, 13, 58, 64, 29, 74, 39, 18, 使用 基数 排序 需要 10 个 箱子( 从 0 ~ 9 标号) 进行 分配 和 收集。 我们 如果 把 每一 个数 看成 由 两个 关键字 构成( 个 位数 和 十 位数), 那么 可以 对 它们 进行 两次 分配 和 收集( 分别 对于 个位 和 十位), 具体 步骤 如下。 (1) 对 序列 的 各个 元素 按 个位 进行 顺序 装箱, 即 45 装入 5 号 箱, 13 装入 3 号 箱, 58 和 18 装入 8 号 箱, 64 和 74 装入 4 号 箱, 29 和 39 装入 9 号 箱。 (2) 从 0 到 9 号 箱 顺序 依次 收集 到 原 序列, 即 3 号 箱 的 13, 4 号 箱 的 64 和 74, 5 号 箱 的 45, 8 号 箱 的 58 和 18, 9 号 箱 的 29 和 39 被 依次 收集。 序列 变为 13, 64, 74, 45, 58, 18, 29, 39。 (3) 对 序列 的 各个 元素 按 十位 进行 顺序 装箱, 即 13 和 18 装入 1 号 箱, 29 装入 2 号 箱, 30 装入 3 号 箱, 45 装入 4 号 箱, 58 装入 5 号 箱, 64 装入 6 号 箱, 74 装入 7 号 箱。 (4) 再次 从 0 到 9 号 箱 顺序 收集 到 原 序列, 序列 变为 13, 18, 29, 30, 45, 58, 64, 74。 此时 完成 基数 排序。 对于 一个 两位 数 来说, 其 十位 数 当然 比 个位 数 关键。 因此 使用 LSD 时, 先 对 个位 数 开始 分配 和 收集。

算法草稿

 

代码实现

#include <stdio.h>
#include <stdlib.h>


#define SUCCESS		0
#define PARAM_ERR	-1

#define BUCKET_NUM	10		/*桶个数*/
#define BUCKET_DEEP	100		/*捅深度*/

/* 
 * 每个桶的头,包含桶元素数组和桶中有效元素的个数
 * 桶元素这里假设只有100个元素,这个限制可以通过链表处理来突破
 */
typedef struct bucket{
	int elem[BUCKET_DEEP];	/*桶元素*/
	int count;				/* 桶元素中有效的个数*/
}st_bucket;


/*
 * 正常桶深应该用链表,这里进行整数的排序,关键字10个,为 0~9
 * 默认可以排序100个数,可以通过将桶元素变为链表来突破这个限制
 */
st_bucket g_buckets[BUCKET_NUM];

/*
 * 初始化 buckets,将所有的桶的有效count设置为0,表示没有有效元素
 */
void InitBuckets(void){
	int i, j;

	for(i = 0; i < BUCKET_NUM; i++){
		g_buckets[i].count = 0;
	}
	
	return;
}


/*
 * 返回array中最大的数
 */
int getMaxNum(int * array, int size){
	
	int i = 0;
	int max = 0;

	max = array[0];
	for(i = 0; i < size; i++){
		if(array[i] > max){
			max = array[i];
		}
	}

	return max;
}


/* 根据num的位数,取得排序的轮数*/
int getRnd(int num){
	int rnd = 0;

	do {
		rnd++;
		num = num / 10;
	} while (0 != num);

	return rnd;
}


int Scatter(int * array, int size, int digit){
	if(NULL == array){
		printf("%s para error\n", __func__);
		return PARAM_ERR;
	}

	int i = 0, num = 0, d = 0;
	int key = 0;  /*桶关键字*/

	for(i = 0; i < size; i++){
		/* 取得桶关键字 */
		num  = array[i];
		for (d = 1; d <= digit; d++){
			key = num % 10;
			num = num / 10;
		}

		/*将数字插入排序桶中*/
		g_buckets[key].elem[g_buckets[key].count++] = array[i];
	}

	return SUCCESS;
}


int gather(int * array, int size) {
	if(NULL == array){
		printf("%s para error\n", __func__);
		return PARAM_ERR;
	}

	int i = 0, j = 0, k = 0;
	int count = 0;

	/*升序*/
	for(i = 0; i < BUCKET_NUM; i++){
		count = g_buckets[i].count;
		for(j = 0; j < count; j++){
			array[k++] = g_buckets[i].elem[j];
		}
	}

	return SUCCESS;
}


int BucketSort(int * array, int size){
	if(NULL == array){
		printf("%s para error\n", __func__);
		return PARAM_ERR;
	}

	int digit = 0;
	int max = 0;
	int rnd = 0;
#ifdef DEBUG
	int i = 0, j = 0, k = 0, c = 0;
#endif

	/*初始化桶*/

	/* 取得最大的数字 */
	max = getMaxNum(array, size);

	/* 取得排序的轮数 */
	rnd = getRnd(max);

	for(digit = 1; digit <= rnd; digit++){
		/* 重新初始化桶*/
		InitBuckets();

		/* 分散到桶中 */
		Scatter(array, size, digit);

		/* 从桶中聚合 */
		gather(array, size);

#ifdef DEBUG
		printf("============= Digit %d =========== \n", digit);				
		printf(" Scattered Bucket:\n");
		/*有序区域*/
		for(i =0; i < BUCKET_NUM; i++){
			printf("\t Bucket[%d]: ", i);
			c = g_buckets[i].count;
			for(j = 0; j < c; j++){
				printf(" %d ", g_buckets[i].elem[j]);
			}
			printf("\n");
		}
		printf(" --------------------------------- \n ");

		/*无序区域*/
		printf("Gattered Array: \n");
		printf("\t");
		for(k =0; k < size; k++){
			printf("  %d  ", array[k]);
		}
		printf("\n");	
		printf("================================== \n\n");
#endif
		
	}

	return SUCCESS;
	
}


int main(int argc, char ** argv){
	int array[10] = {22,32,19,53,0,47,29,116,4,6};
	int i = 0;

	printf("Before sort: \n");
	for(i = 0; i < 10; i++){
		printf("  %d  ", array[i]);
	}
	printf("\n");
	
	BucketSort(array, 10);

	printf("After sort: \n");
	for(i = 0; i < 10; i++){
		printf("  %d  ", array[i]);
	}
	printf("\n");
	
	return 0;
}

调试编译

gcc BucketSort.c -DDEBUG

调试输出

Before sort:
  22    32    19    53    0    47    29    116    4    6
============= Digit 1 ===========
 Scattered Bucket:
         Bucket[0]:  0
         Bucket[1]:
         Bucket[2]:  22  32
         Bucket[3]:  53
         Bucket[4]:  4
         Bucket[5]:
         Bucket[6]:  116  6
         Bucket[7]:  47
         Bucket[8]:
         Bucket[9]:  19  29
 ---------------------------------
 Gattered Array:
          0    22    32    53    4    116    6    47    19    29
==================================

============= Digit 2 ===========
 Scattered Bucket:
         Bucket[0]:  0  4  6
         Bucket[1]:  116  19
         Bucket[2]:  22  29
         Bucket[3]:  32
         Bucket[4]:  47
         Bucket[5]:  53
         Bucket[6]:
         Bucket[7]:
         Bucket[8]:
         Bucket[9]:
 ---------------------------------
 Gattered Array:
          0    4    6    116    19    22    29    32    47    53
==================================

============= Digit 3 ===========
 Scattered Bucket:
         Bucket[0]:  0  4  6  19  22  29  32  47  53
         Bucket[1]:  116
         Bucket[2]:
         Bucket[3]:
         Bucket[4]:
         Bucket[5]:
         Bucket[6]:
         Bucket[7]:
         Bucket[8]:
         Bucket[9]:
 ---------------------------------
 Gattered Array:
          0    4    6    19    22    29    32    47    53    116
==================================

After sort:
  0    4    6    19    22    29    32    47    53    116
发布了191 篇原创文章 · 获赞 43 · 访问量 26万+

猜你喜欢

转载自blog.csdn.net/leoufung/article/details/104329157