乱七八糟和桶排序(Bucket Sort)

Posted 跳跳揽月

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了乱七八糟和桶排序(Bucket Sort)相关的知识,希望对你有一定的参考价值。

天秤左边


感觉很多事没做,可是自己又什么事都不想做,懒懒的,起床后连洗漱都懒得动,醒着看了几段抖音,昨晚还是感叹高手在民间,今天却看到腾讯出了个微视,联合了很多101女孩,一丝一模模仿抖音,这个社会就是这样,当你强大到足够的力量,即使抄袭都那么理直气壮。冰冰说,如果学不会从容,那就更要尊重内心那一小块玉的质地。我喜欢她这句话,这话显得跟现今社会是那样的格格不入,那样倔强,又那样骄傲。


天秤的右边


桶排序也叫箱排序。工作的原理是将数组元素映射到有限数量个桶里,利用计数排序可以定位桶的边界,每个桶再各自进行桶内排序(使用其它排序算法或以递归方式继续使用桶排序)。

桶排序的实现代码如下:

#include<iostream>

using namespace std;

 

// 分类 ------------- 内部非比较排序

// 数据结构 --------- 数组

// 最差时间复杂度 ---- O(nlogn)或O(n^2),只有一个桶,取决于桶内排序方式

// 最优时间复杂度 ---- O(n),每个元素占一个桶

// 平均时间复杂度 ---- O(n),保证各个桶内元素个数均匀即可

// 所需辅助空间 ------ O(n + bn)

// 稳定性 ----------- 稳定

 

/* 本程序用数组模拟桶 */

const int bn = 5;    // 这里排序[0,49]的元素,使用5个桶就够了,也可以根据输入动态确定桶的数量

int C[bn];           // 计数数组,存放桶的边界信息

 

void InsertionSort(int A[], int left, int right)

{

    for (int i = left + 1; i <= right; i++)  // 从第二张牌开始抓,直到最后一张牌

    {

        int get = A[i];

        int j = i - 1;

        while (j >= left && A[j] > get)

        {

            A[j + 1] = A[j];

            j--;

        }

        A[j + 1] = get;

    }

}

 

int MapToBucket(int x)

{

    return x / 10;    // 映射函数f(x),作用相当于快排中的Partition,把大量数据分割成基本有序的数据块

}

 

void CountingSort(int A[], int n)

{

    for (int i = 0; i < bn; i++)

    {

        C[i] = 0;

    }

    for (int i = 0; i < n; i++)     // 使C[i]保存着i号桶中元素的个数

    {

        C[MapToBucket(A[i])]++;

    }

    for (int i = 1; i < bn; i++)    // 定位桶边界:初始时,C[i]-1为i号桶最后一个元素的位置

    {

        C[i] = C[i] + C[i - 1];

    }

    int *B = (int *)malloc((n) * sizeof(int));

    for (int i = n - 1; i >= 0; i--)// 从后向前扫描保证计数排序的稳定性(重复元素相对次序不变)

    {

        int b = MapToBucket(A[i]);  // 元素A[i]位于b号桶

        B[--C[b]] = A[i];           // 把每个元素A[i]放到它在输出数组B中的正确位置上

                                    // 桶的边界被更新:C[b]为b号桶第一个元素的位置

    }

    for (int i = 0; i < n; i++)

    {

        A[i] = B[i];

    }

    free(B);

}

 

void BucketSort(int A[], int n)

{

    CountingSort(A, n);          // 利用计数排序确定各个桶的边界(分桶)

    for (int i = 0; i < bn; i++) // 对每一个桶中的元素应用插入排序

    {

        int left = C[i];         // C[i]为i号桶第一个元素的位置

        int right = (i == bn - 1 ? n - 1 : C[i + 1] - 1);// C[i+1]-1为i号桶最后一个元素的位置

        if (left < right)        // 对元素个数大于1的桶进行桶内插入排序

            InsertionSort(A, left, right);

    }

}

 

int main()

{

    int A[] = { 29, 25, 3, 49, 9, 37, 21, 43 };// 针对桶排序设计的输入

    int n = sizeof(A) / sizeof(int);

    BucketSort(A, n);

    printf("桶排序结果:");

    for (int i = 0; i < n; i++)

    {

        printf("%d ", A[i]);

    }

    printf("\n");

    return 0;

}


下图给出了对{ 29, 25, 3, 49, 9, 37, 21, 43 }进行桶排序的简单演示过程

桶排序不是比较排序,不受到O(nlogn)下限的影响,它是鸽巢排序的一种归纳结果,当所要排序的数组值分散均匀的时候,桶排序拥有线性的时间复杂度。


以上是关于乱七八糟和桶排序(Bucket Sort)的主要内容,如果未能解决你的问题,请参考以下文章

一堆乱七八糟绝不正经的排序算法

一些乱七八糟的数学结论

桶排序(Bucket Sort)

桶排序(bucket sort)

bucket sort 桶排序

排序算法:Bucket Sort 桶排序