• 桶排序


    桶排序

    桶排序(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


    若有所帮助。顶一个哦!


    专栏文件夹:


  • 相关阅读:
    机器学习sklearn(66):算法实例(二十三)SVM(一)概述
    机器学习sklearn(65):算法实例(二十二)聚类(五)KMeans (四) 总结
    机器学习sklearn(64):算法实例(二十一)聚类(四)KMeans (三) 案例:聚类算法用于降维,KMeans的矢量量化应用
    机器学习sklearn(63):算法实例(二十)聚类(三)KMeans (二) sklearn.cluster.KMeans
    机器学习sklearn(62):算法实例(十九)聚类(二)KMeans
    机器学习sklearn(61):算法实例(十八)聚类(一)概述
    机器学习sklearn(60):算法实例(十七)分类(十)逻辑回归(五)附录
    机器学习sklearn(59):算法实例(十六)分类(九)逻辑回归(四)实例 用逻辑回归制作评分卡
    机器学习sklearn(58):算法实例(十五)分类(八)逻辑回归(三)linear_model.LogisticRegression(二) 重要参数
    机器学习sklearn(57):算法实例(十四)分类(七)逻辑回归(二)linear_model.LogisticRegression(一) 重要参数
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5123544.html
Copyright © 2020-2023  润新知