zoukankan      html  css  js  c++  java
  • 桶排序

    桶排序

    桶排序(Bucket Sort)是对基数排序的一个变种。

    在排序过程中没实用到计数数组。而是用不同的桶来临时存储keyword。看一个示意图:

    排序序列 123 234 45 111 6 128


    整个过程就是在不断地分配、收集。

    而且每个桶都是队列。所以收集的时候得按先进先出的原则,且从第0个桶開始收集。

    在实际应用中。依据桶的创建策略,桶排序也有不同的写法。以下给出两种不同的桶创建方式。

    一、使用静态队列创建桶。二、使用二维数组模拟桶。

    静态队列桶

    #include<iostream>
    #include<iomanip>
    using namespace std;
    //记录类型
    typedef struct record
    {
    	int key;
    	int next;
    }Record;
    //静态队列
    typedef struct queue
    {
    	//队头
    	int head;
    	//队尾
    	int tail;
    }StaticQueue;
    //获取最大位数
    int get_max_digit(int array[], int n)
    {
    	int digit, max;
    	digit = 0;
    	max = array[0];
    	for (int i = 1; i < n; i++)
    	{
    		if (array[i] > max)
    			max = array[i];
    	}
    	while (max)
    	{
    		digit++;
    		max /= 10;
    	}
    	return digit;
    }
    
    /*
    收集
    把10个桶连接起来
    */
    void collect(Record rec[], StaticQueue queue[], int& first)
    {
    	//k是桶号
    	int tail, k = 0;
    	//先找到第一个非空的桶
    	while (queue[k].head == -1)
    		k++;
    	//用first记录第一个记录的位置,为下次分配使用
    	first = queue[k].head;
    	tail = queue[k].tail;
    	while (k < 9)
    	{
    		k++;
    		while (k < 9 && queue[k].head == -1)
    			k++;
    		//把上一个桶的尾部和当前桶的头部连接起来
    		if (queue[k].head != -1)
    		{
    			rec[tail].next = queue[k].head;
    			tail = queue[k].tail;
    		}
    	}
    	rec[tail].next = -1;
    }
    
    /*
    分配
    把n个记录分配到10个桶中
    r:从右数按第r位排序(r=1,2...)
    first:第一个记录的下标
    */
    void distribute(Record rec[], int r, int first, StaticQueue queue[])
    {
    	//先把队列初始化
    	int i, d, cur = first;
    	for (i = 0; i < 10; i++)
    		queue[i].head = -1;
    
    	i =  d = 1;
    	while (i < r)
    	{
    		i++;
    		d *= 10;
    	}
    	int k;
    	//把记录分配每个桶中
    	while (cur != -1)
    	{
    		k = (rec[cur].key / d) % 10;
    		//桶空,则当前记录是第一个
    		if (queue[k].head == -1)
    			queue[k].head = cur;
    		else//桶非空,则当前记录连接到尾部
    			rec[queue[k].tail].next = cur;
    		//改动队列尾部,这一句不可忘了
    		queue[k].tail = cur;
    		//继续给下一个记录分桶
    		cur = rec[cur].next;
    	}
    }
    
    /*
    重排
    first:第一个记录的下标
    */
    void arrange(Record rec[], int n, int first)
    {
    	int i, j = first;
    	Record temp;
    	for (i = 0; i < n - 1; i++)
    	{
    		temp = rec[j];
    		rec[j] = rec[i];
    		rec[i] = temp;
    		rec[i].next = j;
    		j = temp.next;
    		while (j <= i)
    			j = rec[j].next;
    	}
    }
    
    /*
    基数排序
    array:待排序序列
    n:序列大小
    */
    void RadixSort(int array[], int n)
    {
    	//对排序序列进行封装
    	int i;
    	Record *rec = new Record[n];
    	for (i = 0; i < n; i++)
    	{
    		rec[i].key = array[i];
    		rec[i].next = i + 1;
    	}
    	rec[n - 1].next = -1;
    	/*
    	创建静态队列,每个队列相当于一个桶
    	对于十进制数。仅仅需10个桶就可以
    	*/
    	StaticQueue queue[10];
    	//获取最大排序位数
    	int digit = get_max_digit(array, n);
    	int first = 0;
    	for (i = 1; i <= digit; i++)
    	{
    		distribute(rec, i, first, queue);
    		collect(rec, queue, first);
    	}
    	//重排
    	arrange(rec, n, first);
    	//回放
    	for (i = 0; i < n; i++)
    		array[i] = rec[i].key;
    	//释放空间
    	delete[]rec;
    }
    
    //打印
    void print(int array[], int n)
    {
    	for (int i = 0; i < n; i++)
    		cout << setw(6) << array[i];
    	cout << endl;
    }
    
    int main()
    {
    	cout << "******桶排序(静态队列)***by David***" << endl;
    	int array[] = { 123, 234, 45, 111, 6, 128 };
    	int n = sizeof(array) / sizeof(int);
    	cout << "原序列" << endl;
    	print(array, n);
    	cout << "桶排序" << endl;
    	RadixSort(array, n);
    	print(array, n);
    	system("pause");
    	return 0;
    }

    执行


    代码下载:桶排序(静态队列)

    二维数组桶  

    #include<iostream>
    #include<iomanip>
    using namespace std;
    //最大排序个数
    const int N = 12;
    //分配
    void distribute(int array[], int n, int bucket[][N+1], int r)
    {
    	int i;
    	//对桶进行初始化。bucket[i][0]存放的是第i个桶中元素个数
    	for (i = 0; i < 10; i++)
    		bucket[i][0] = 0;
    	int d;
    	i = d = 1;
    	while (i < r)
    	{
    		d *= 10;
    		i++;
    	}
    	int k;
    	for (i = 0; i < n; i++)
    	{
    		k = (array[i] / d) % 10;
    		bucket[k][0]++;
    		bucket[k][bucket[k][0]] = array[i];
    	}
    }
    //收集
    void collect(int array[], int n, int bucket[][N+1])
    {
    	int i, j, index;
    	index = 0;
    	for (i = 0; i < 10; i++)
    	for (j = 1; j <= bucket[i][0]; j++)
    		array[index++] = bucket[i][j];
    }
    //获取最大位数
    int get_max_digit(int array[], int n)
    {
    	int digit, max;
    	digit = 0;
    	max = array[0];
    	for (int i = 1; i < n; i++)
    	{
    		if (array[i] > max)
    			max = array[i];
    	}
    	while (max)
    	{
    		digit++;
    		max /= 10;
    	}
    	return digit;
    }
    //桶排序
    void BucketSort(int array[], int n)
    {
    	int digit = get_max_digit(array, n);
    	int i;
    	int bucket[10][N+1];
    	for (i = 1; i <= digit; i++)
    	{
    		//分配
    		distribute(array, n, bucket, i);
    		//收集
    		collect(array, n, bucket);
    	}
    }
    //打印
    void print(int *a, int n)
    {
    	for (int i = 0; i < n; i++)
    		cout << setw(6) << a[i];
    	cout << endl;
    }
    int main()
    {
    	cout << "******桶排序(二维数组)***by David***" << endl;
    	int array[] = { 123, 234, 45, 111, 6, 128 };
    	int n = sizeof(array) / sizeof(int);
    	cout << "原序列" << endl;
    	print(array, n);
    	cout << "桶排序" << endl;
    	BucketSort(array, n);
    	print(array, n);
    	system("pause");
    	return 0;
    }

    执行



    代码下载:桶排序(二维数组)


    小结

    上面的两种方式都是桶排序的详细实现。整体上是分配和收集的过程。只是细节非常多,须要细致看代码。


    转载请注明出处,本文地址:http://blog.csdn.net/zhangxiangdavaid/article/details/37668921


    若有所帮助。顶一个哦!


    专栏文件夹:


  • 相关阅读:
    希望走过的路成为未来的基石
    第三次个人作业--用例图设计
    第二次结对作业
    第一次结对作业
    第二次个人编程作业
    第一次个人编程作业(更新至2020.02.07)
    Springboot vue 前后分离 跨域 Activiti6 工作流 集成代码生成器 shiro权限
    springcloud 项目源码 微服务 分布式 Activiti6 工作流 vue.js html 跨域 前后分离
    spring cloud springboot 框架源码 activiti工作流 前后分离 集成代码生成器
    java代码生成器 快速开发平台 二次开发 外包项目利器 springmvc SSM后台框架源码
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5123544.html
Copyright © 2011-2022 走看看