基础班第三课 桶排序:不基于比较的排序(左神算法听课笔记)

本章知识点:

  • 比较器(重载运算符)
  • 计数排序
  • 基数排序

Part 1 : 比较器

什么是比较器(以Java为例子)

比较器是一个这样的函数:

  • 参数是两个待比较的对象
  • 函数返回负数的时候,表示第一个参数排在前面。
  • 函数返回正数的时候,表示第二个参数排在前面。
    (有一些特定的数据结构或者方法就要求提供比较器:sort方法之类的)

比较器的使用:

  • 比较器的本质是重载运算符
  • 可以应用在特殊的排序上(自定义的排序) or 根据特殊标准的排序(只按照对象中的一个数值进行排序)

实现改进:作差法直接起飞了

public static int comparator(object A, object B) {
	return A - B;
}

Part 2 : 不基于比较的排序 桶排序

像这类不基于比较的排序多多少少都是和数据情况有关。
基于比较的排序只需要比较规则,所以使用范围很广。而不基于比较的排序因为需要额外信息所以适用范围就相对小。

不基于比较但是基于分类

计数排序

  • 初始化max
  • 找到数组中的最大数字作为max
  • 创建max个桶
  • 遍历数组,把数据放进桶里面
  • 把桶里面的数据还原成数组
//很easy的codeing,没有技术含量
public static void countSort(int[] arr) {  
    if(arr == null || arr.length < 2) {  
        return;  
    }  
    int max = Integer.MIN_VALUE;  
    for(int i = 0; i < arr.length; i++) {  
        max = Math.max(max,arr[i]);  
    }  
    //创建桶  
    int[] bucket = new int[max+1];  
  
    //入桶  
    for(int i = 0; i < arr.length; i++) {  
       bucket[arr[i]]++;  
    }  
    //桶中数据还原成数组  
    int i = 0;  
    for(int j = 0; j < bucket.length; j++) {  
        while (bucket[j]-- > 0){  
            arr[i++] = j;  
        }  
    }  
}

就是用桶来分类统计然后还原回去就好了。

基数排序

计数统计有几个数就要用几个桶,太浪费空间了!
基数统计稍微高级一点,但是要求被统计的数字要有“进制规则”或者说是优先级。
这里的桶是队列,先入桶的要先出桶。

桶的顺序是从大到小。
这里使用队列来优化空间了,只使用一个count数组就解决出桶入桶的问题,没有能进制个桶:

//要用到的子操作  
// 1.返回数组中最大数的位数  
public static int maxbits(int[] arr) {  
    //或许可以使用堆来快速找到最大值?没有加速 都是O(n)  
    int max = Integer.MIN_VALUE;  
    for(int i = 0; i < arr.length; i++) {  
        max = Math.max(max, arr[i]);  
    }  
  
    int res = 0;  
    while(max != 0) {  
        max /= 10;  
        res++;  
    }  
  
    return res;  
}  
  
// 2.返回数字k的第d个数字  
public static int getDigit(int x, int d) {  
    //别想着循环一个个除了^^  
    //x / ((int) Math.pow(10, d - 1))去掉从个位(1位)到d-1位的数字  
    //在取个位数的模  
    return ((x / ((int) Math.pow(10, d - 1))) % 10);  
    }
//桶排序

//程序入口  
public static void radixSort(int[] arr) {  
    if(arr == null || arr.length < 2) {  
        return;  
    }  
    radixSort(arr,0,arr.length - 1, maxbits(arr));  
}  
  
public static void radixSort(int[] arr, int begin, int end,int digit) {  
    final int raidx = 10;  
    int i = 0, j = 0;  
    //中间数组,用来存放出桶之后的数据  
    int[] bucket = new int[end - begin + 1];  
  
    //开始桶排序  
    for(int d = 1; d <= digit; d++) {  
        int[] count = new int [raidx];  
        //入桶  
        //1. 统计第d位数字为i的数字个数  
        for(i = begin; i <= end; i++) {  
            j = getDigit(arr[i],d);  
            count[j]++;  
        }  
        //2. 累加个数得到第d位数字小于等于i的数字个数  
        for(i = 1; i < raidx; i++){  
            count[i] = count[i] + count[i - 1];  
        }  
  
        //出桶  
        for(i = end ;i >= begin; i--) {  
            j = getDigit(arr[i],d);  
            bucket[count[j] - 1] = arr[i];  
            count[j]--;  
        }  
  
        //写回原数组  
        for(i = begin, j = 0; i <= end ; i++, j++){  
            arr[i] = bucket[j];  
        }  
  
    }  
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值