clllll  

排序可以分为俩种: 基于比较的排序和不基于比较的排序(根据数据的状况。。。。)
申请额外的数组进行 频率统计。 根据数据的大小, 分配大小。
词频 统计
计数排序:统计词频
基数排序:根据个位数,十位数,百位数,放。要排序的对象 要有进制。
根据个位数放。放完之后,倒出来,同一个桶的数据先进先出

然后根据十位数放。一样

入桶出桶的次数和最大值有关。

计数排序

要了解数据的情况,最大值,最小值。

public void userSort(int[] arr) {
    if (arr == null || arr.length < 2) {
        return;
    }

    // max 代表当前数组里的最大数
    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]; // 辅助数组,size = max + 1

    // 遍历原始数组,构造辅助数组。
    for (int i = 0; i < arr.length; i++) {
        bucket[arr[i]]++; // 当前值 的下标在辅助数组 累积+1
    }

    // 遍历辅助数组,依次打印,
    int index = 0; // 原数组下标 变量,依次递增
    for (int i = 0; i < bucket.length; i++) {
        while (bucket[i] > 0) {
            arr[index] = i;
            index++;
            bucket[i]--;
        }
    }

python 实现

def user_sort(self, arr):
    import sys
    max_num = -sys.maxsize - 1
    for item in arr:
        max_num = max(max_num, item)
    bucket = []
    for i in range(2*max_num + 1):
        bucket.append(0)
    for item in arr:
        bucket[item] += 1
    
    index = 0
    for i,item in enumerate(bucket):
        while item > 0:
            arr[index] = i
            index +=1
            item -= 1

基数排序

@Override
public void userSort(int[] arr) {
    // 数 都是非负数
    int jiweishu = maxbits(arr);
    radixSort(arr, 0, arr.length - 1, maxbits(arr));

}

public static int maxbits(int[] arr) {
    // 获取当前数组最大的数 是几位。
    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) {
        res++;
        max /= 10;
    }

    return res;
}

public static int getDigit(int x, int d) {
    return ((x / ((int) Math.pow(10, d - 1))) % 10);
}

public static void radixSort(int[] arr, int l, int r, int digit) {
    int radix = 10; // 十进制的数
    int i = 0;
    int j = 0;

    int[] bucket = new int[r - l + 1]; // 辅助数组,和原数组等规模
    // 外层for循环控制 进出桶的次数,从个位开始,最大数是三位数,就进出桶三次
    for (int d = 1; d <= digit; d++) {
        // d代表当前位, 个位还是十位还是百位
        // 值代表当前位 的 词频
        int[] count = new int[radix]; // 桶 0, 1, 2, 3, 4,5, 6, 7 , 8 ,9

        // 进桶
        for (i = l; i <= r; i++) {
            j = getDigit(arr[i], d);
            count[j]++;
        }
        // 加工一下,词频数组count 变为前缀和,以前是个位数字i == value 的个数,现在是 i <= value 的个数
        for (i = 1; i < radix; i++) {
            count[i] = count[i] + count[i - 1];
        }

        // 从右往左(先入桶的先出), 比如 <= 2 的数有4个。 出桶
        for (i = r; i >= l; i--) {
            j = getDigit(arr[i], d);
            bucket[count[j] - 1] = arr[i]; // 当前值应该放在辅助数组的哪个位置。
            count[j]--; // 当前值前缀和 -1,后面的不管,各自使用各自的片
        }

        // 辅助数组 复制 回 原数组
        for (i = l, j = 0; i <= r; i++, j++) {
            arr[i] = bucket[j];
        }
    }
}

python 实现

class RadixSort(ArrayUtil):
    def user_sort(self, arr):
        radix = 10 
        
        bucket = [ 0 for x in range(len(arr))]
        max_d = self.get_max_digit(arr)
        for d in range(1, max_d + 1):
            count = [0 for x in range(radix)] 
            for item in arr:
                cur_d = self.get_digit(item, d)
                count[cur_d] += 1
            
            for index in range(1, radix):
                count[index] = count[index] + count[index-1]
            
            for item in arr[::-1]:
                cur_d = self.get_digit(item, d)
                bucket[count[cur_d] - 1 ] = item
                count[cur_d] -= 1

            for index, item in enumerate(bucket):
                arr[index] = item 

    def get_max_digit(self, arr):
        import sys 
        max_num = -sys.maxsize - 1
        for item in arr:
            max_num = max(max_num, item)
        res = 0
        while max_num != 0:
            res += 1
            max_num = max_num /10 
        return res 
    
    def get_digit(self, num, d):
        # 获取一个数的第几位,数
        tmp_10_pow = pow(10, d - 1)
        return int((num / (tmp_10_pow)) % 10 )

边界值一定要思考。不急慢慢来

posted on 2022-05-01 22:30  llcl  阅读(30)  评论(0编辑  收藏  举报