Java数据结构与算法20

第20章 基数排序

20.1 基数排序概念

基数排序(Radix Sort)是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前

排序步骤

  • 取得数组中的最大数,并取得位数;
  • arr为原始数组,从最低位开始取每个位组成radix数组;
  • 对radix进行计数排序(利用计数排序适用于小范围数的特点)

动图展示


静图分析

20.2 代码实现

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

import java.util.Arrays;public class RadixSort {

    public static void main(String[] args) {

        int[] arr = {4, 32, 457, 16, 28, 64};

        radixSort(arr);//        [32, 4, 64, 16, 457, 28]//        [4, 16, 28, 32, 457, 64]//        [4, 16, 28, 32, 64, 457]

    }

    //基数排序

    public static void radixSort(int[] arr) {

        // 定义临时二维数组表示十个桶

        int[][] temp = new int[10][arr.length];

        // 定义一个一维数组,用于记录在temp中相应的数组中存放数字的数量

        int[] counts = new int[10];

        //存数组中最大的数字

        int max = Integer.MIN_VALUE;

        for (int i = 0; i < arr.length; i++) {

            if (arr[i] > max) {

                max = arr[i];

            }

        }

        //计算最大数字是几位数(才能知道排序次数)

        int maxLength = (max + "").length();

        //根据最大长度的数决定比较的次数

        for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {

            //把每一个数字分别计算余数

            for (int j = 0; j < arr.length; j++) {

                //计算余数

                int ys = arr[j] / n % 10;

                //把当前遍历的数据放入指定的数组中

                temp[ys][counts[ys]] = arr[j];

                //记录数量

                counts[ys]++;

            }

            //记录取的元素需要放的位置

            int index = 0;

            //把数字取出来

            for (int k = 0; k < counts.length; k++) {

                //记录数量的数组中,当前余数记录的数量不为0才取

                if (counts[k] != 0) {

                    //循环取出元素

                    for (int l = 0; l < counts[k]; l++) {

                        //取出元素

                        arr[index] = temp[k][l];

                        //记录下一个位置

                        index++;

                    }

                    //把数量置为0

                    counts[k] = 0;

                }

            }

            //打印每次排序后的结果

            System.out.println(Arrays.toString(arr));

        }

    }}

20.3 时间复杂度

  • 最优时间复杂度:O(n^k)
  • 最坏时间复杂度:O(n^k)
  • 稳定性:稳定

初看起来,基数排序的执行效率似乎好的让人无法相信,所有要做的只是把原始数据项从数组复制到链表,然后再复制回去。如果有10个数据项,则有20次复制,对每一位重复一次这个过程。假设对5位的数字排序,就需要20 * 5=100次复制。

*如果有100个数据项,那么就有200 * 5=1000次复制。复制的次数与数据项的个数成正比,即O(n)。这是我们看到的效率最高的排序算法。

不幸的是,数据项越多,就需要更长的关键字,如果数据项增加10倍,那么关键字必须增加一位(多一轮排序)。复制的次数和数据项的个数与关键字长度成正比,可以认为关键字长度是N的对数。因此在大多数情况下,基数排序的执行效率倒退为O(N*logN),和快速排序差不多

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值