• 【数据结构】排序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));
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    算法分析

    时间复杂度: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;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    计数排序(Count Sort)

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

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

    计数排序算法

    #include
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

  • 相关阅读:
    【操作系统】进程空间管理
    《第一堂棒球课》:王牌三垒手·棒球5号位
    【WPF应用30】WPF中的ListBox控件详解
    【MySQL】数据库进阶之触发器内容详解
    数学才是顶级码农的核心修养,码农怎样搞好数学?来看看这些网友强推的数学神作!文末评论区进行评论参与送书哟
    加拿大海运渠道操作流程及注意事项
    Uniapp离线打包SDK-模块配置
    MySQL锁机制详解-表锁与行锁
    C++ vector 功能强大的数组
    pthread_mutex_t & pthread_cond_t 总结
  • 原文地址:https://blog.csdn.net/weixin_54007670/article/details/127524832