【数据结构】排序6——桶排序、基数排序、计数排序


基数排序是基于桶排序的一种排序,
基数排序可以看作桶排序。

桶排序是按值域划分桶,
基数排序是按位数划分桶。

基数排序(Radix Sort)

分类(LSD和MSD):
① 最低位优先LSD法:先从最低位开始排序,再对次低位排序,直到对最高位排序后得到一个有序序列。
② 最高位优先MSD法:先从最高位开始排序,再对次高位排序,直到对最低位排序后得到一个有序序列。

【基本思想】
分配+收集
① 基数排序也叫桶排序或箱排序:设置若干个箱子,将关键字为的记录放入第k个箱子,然后在按序号将非空的连接。
② 要求箱子个数是有范围的,例如:数字是有范围的,均由0-9这十个数字组成,则只需设置十个箱子,相继按个、十、百…进行排序。

例:
(614,738,921,485,637,101,215,530,790,306)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

基数排序算法

void radixsort(int num[],int len)
{
	int i,j,k,l,digit;
	int allot[10][N];
	memset(allot,0,sizeof(allot));
	for(i=1;i<=D;i++)
	{
		int flag=0;
		for(j=0;j<len;j++)
		{
			digit=getdigit(num[j],i);
			k=0;
			while(allot[digit][k])
			k++;
			allot[digit][k]=num[j];
			if(digit)
			flag=1;
		}
		if(!flag)
		break;
		l=0;
		for(j=0;j<10;j++)
		{
			k=0;
			while(allot[j][k]>0)
			{
				num[l++]=allot[j][k];
				k++;
			}
		}
		memset(allot,0,sizeof(allot));
	}
}

算法分析

时间复杂度:O(k*(n+m))
关键字:分配的标准,如按百位排序,按千位排序……
k:关键字个数,表示分配多少趟。
m:关键字取值范围为m个值,也就是桶的个数。
n:元素个数。
在这里插入图片描述

空间复杂度:S(n)=O(n+m)

稳定性:稳定

优点:算法效率高;
缺点:关键字的取值范围有限。

桶排序(Bucket Sort)

“桶排序”又称“箱排序”。

【基本思想】
桶排序是将待排序序列中处于相同值域的元素存入同一个桶中,即将一个数据表分割成许多桶,然后每个桶中的元素各自排序。它采用分治策略,是一种分布式的排序方法。

【基本步骤】
① 根据待排序序列中最大元素和最小元素的差值和映射规则,确定申请的桶个数;
② 遍历待排序序列,将每一个元素存储到对应的桶中;
③ 分别对每一个桶中元素进行排序,并存储到原序列中,获得一个已排序序列。

桶排序算法

bool buckertSort(int array[], size_t arrLen, size_t bucketSize) {
    const int DEFAULT_BUCKET_SIZE = 10;
    if(arrLen < 2) {
        return true;
    }

    if (bucketSize < 1) {
        bucketSize = DEFAULT_BUCKET_SIZE;
    }

    // Find the scope of the array
    int min = array[0];
    int max = array[0];

    for (size_t i = 1; i < arrLen; ++i)
    {
        if (min > array[i]) {
            min = array[i];
        }
        else if (max < array[i]) {
            max = array[i];
        }
    }

    // Create buckets
    int **buckets = new int*[bucketSize]();//创建桶
    int *bucketLen = new int[bucketSize]();//创建记录当前桶内数据个数,初始化为0
    //计算桶的数据的范围,可以把它想象为把一个线段,平均分成bucketSize个小线段,小线段的长度就是bucketScope
    //为什么+1,大家知道min=10,max=90,其实有81个数据,如果按照(90-10)/10来分,你桶里面的数据范围只能从10到89,所以要用1补齐
    int bucketScope = floor((max - min)/bucketSize) + 1; 

    //创建桶空间,只有桶里面有空间才能放数据
    for (size_t j = 0; j < bucketSize; j++)
    {
        buckets[j] = new int[arrLen]();
    }

    int bucketIndex = -1;

    // Put array value to buckets
    for (size_t k = 0; k < arrLen; ++k)
    {
        bucketIndex = floor((array[k] - min)/bucketScope); //计算数据所在桶的下标
        buckets[bucketIndex][bucketLen[bucketIndex]++] = array[k];//将数据放入桶中
    }

    // Sort value in bucket and put ordered value back to array
    int arrayIndex = 0;
    for (size_t l = 0; l < bucketSize; l++)
    {
        if (bucketLen[l] > 0) {
            insertSort(buckets[l], bucketLen[l]); //对桶内数据进行排序
            for (size_t m = 0; m < bucketLen[l]; ++m) {
                array[arrayIndex++] = buckets[l][m];//将排好序的数据放回原数组
            }
        }
        delete [] buckets[l];
        buckets[l] = NULL;
    }

    delete [] buckets;
    delete [] bucketLen;

    return true;

}

计数排序(Count Sort)

【基本思想】
若待排序序列的元素均为非负整数,且最大值为max,则分配max+1个桶,每个桶的编号(下标)就等于待排序元素的值,每个桶的元素值就是存入桶中的待排序元素个数。为了描述方便,我们将桶序列称为统计数组。

【基本步骤】
(1)根据待排序序列中最大元素值,确定申请的桶个数,并将桶全部清空;
(2)统计待排序序列中每个值为i的元素出现的次数,存入编号为i的桶;
(3)依次把数据从桶里倒出来,存储到原序列中,获得一个已排序序列。

计数排序算法

#include<iostream>
using namespace std;
int main()
{
	int arr[]={3,5,6,9,5,2,4,7};
	int len=8;
	int count[8]={0};//9-2+1
	for(int i=0;i<len;i++)
	{
		count[arr[i]]++;
	}
	for(int i=0;i<8;i++)
	{
		while(count[i]!=0)
		{
			cout<<i<<" ";
			count[i]--;
		}
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值