《啊哈!算法》简单桶排序(Simple Bucket Sort)

17 篇文章 0 订阅
2 篇文章 0 订阅

《啊哈!算法》简单桶排序(Simple Bucket Sort)

首先想想如何简单地排序?

假设我们有5个学生,分数分别是5, 3, 5, 2, 8,满分10分。

由实际可知,分数范围在[0,10],闭区间范围内。

首先申请一个一维数组int arr[11], 是从[0, 10]。

这里认为第i个元素代表得i分的人的数目。

比如i=0,arr[0]=3,那么代表得0分的人有三个。

首先第一个人分数是5,那么就arr[5]=arr[5]+1;

第二个人分数是3,那么就arr[3]=arr[3]+1;

第三个人分数是5,那么就arr[5]=arr[5]+1;

第四个人分数是2,那么就arr[2]=arr[2]+1;

第五个人分数是8,那么就arr[8]=arr[8]+1;

然后再依次输出即可(或者置回对应的位置)。

a[2]为1表示2出现过一次,那么就输出一个2;
a[n]为m表示n出现过m次,那么就输出m个n;

C Code:

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

#define SAFE_FREE(p) {free(p);p=NULL;}

/************************************************
 * 函数名称:print_array
 * 参数列表:1.int *parray:一个int类型指针,指向一个数组首地址
 *           2.int n:一个int类型变量,指明数组大小
 * 函数描述:输出数组中每个元素
 * 返回值  :void
 * Author  :test1280
 * History :2017/04/14
 * *********************************************/
void print_array(int *parray, int n)
{
    int i;
    for (i=0; i<n; i++)
    {
        printf("%d ", parray[i]);
    }
    printf("\n");
}

/**********************************************
 * 函数名称:bucketSort
 * 参数列表:
 * int *parr:待排序数组起始位置
 * int n:有多少个元素
 * int buckets:有多少个桶(即最大的位置)
 * 函数描述:简化版桶排序
 * Author  :test1280
 * History :2017/04/18
 * **********************************************/
void bucketSort(int *parr, int n, int buckets)
{
    int *res = (int *)malloc(sizeof(int) * (buckets + 1));
    if (res == NULL)
    {
        return ;
    }

    memset(res, 0, sizeof(int) * (buckets + 1));

    int i=0;
    while (i<n)
    {
        res[parr[i]]++;
        i++;
    }

    int index = 0;
    for (i=0; i <= buckets; i++)
    {
        while (res[i]--)
        {
            parr[index++] = i;
        }
    }

    SAFE_FREE(res);
}

int main()
{
    int arr[] = {8, 100, 50, 22, 15, 6, 1, 1000, 999, 0, 0, 50, 1};

    printf("before sort:\n");
    print_array(arr, 13);

    bucketSort(arr, 13, 1000);

    printf("after sort:\n");
    print_array(arr, 13);

    return 0;
}

(注:我的代码和原书中有些不一样。)

输出结果:

[test1280@localhost sort]$ ./main
before sort:
8 100 50 22 15 6 1 1000 999 0 0 50 1 
after sort:
0 0 1 1 6 8 15 22 50 50 100 999 1000

这样排序的特点是,必须知道值得范围,然后做一下映射,记录在一个数组里面。

我个人认为,很有点Hash。

刚刚是从小到大进行排序,从大到小进行排序只需要修改一下遍历的顺序即可。

/**********************************************
 * 函数名称:bucketSort
 * 参数列表:
 * int *parr:待排序数组起始位置
 * int n:有多少个元素
 * int buckets:有多少个桶(即最大的位置)
 * 函数描述:简化版桶排序
 * Author  :test1280
 * History :2017/04/18
 * **********************************************/
void bucketSort(int *parr, int n, int buckets)
{
    int *res = (int *)malloc(sizeof(int) * (buckets + 1));
    if (res == NULL)
    {
        return ;
    }

    memset(res, 0, sizeof(int) * (buckets + 1));

    int i=0;
    while (i<n)
    {
        res[parr[i]]++;
        i++;
    }

    int index = 0;
    for (i=buckets; i >=0; i--)
    {
        while (res[i]--)
        {
            parr[index++] = i;
        }
    }

    SAFE_FREE(res);
}

输出结果:

[test1280@localhost sort]$ ./main
before sort:
8 100 50 22 15 6 1 1000 999 0 0 50 1 
after sort:
1000 999 100 50 50 22 15 8 6 1 1 0 0

桶排序简单易懂,但是存在一些问题:

1.如果只有3个数需要排序,但是最大的和最小的相差20000,那么就有很多的空间被浪费;

2.如果是小数,或者别的比较难以映射成整数的情形下,比较难处理。

文中也提到,真正的桶排序要比这个复杂一些,后续我看到再进行记录整理。

注:此篇Blog为读《啊哈!算法》笔记。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值