[算法] 关于algs4 MSD.java 高位优先的字符串排序 的逐行代码解释

引用资料

[1] algs4 MSD.java 完整代码实现
http://algs4.cs.princeton.edu/51radix/MSD.java.html

[2] 搭建java环境 以及安装algs4程序(win版本,其余可参考官网for students部分)
http://algs4.cs.princeton.edu/windows/

说明

  • 完整源码(见引用[1]);

  • 环境设置(见引用[2]);

  • 这个精彩的实现值得花时间一行一行怼明白;

MSD

  • 高位优先的字符串排序(most significant digit first) :
    • 从左往右,递归排序;
    • 适合于字符串长度不一的情况;
    • 出现大量重复的字符串是最坏;

字母表 基数R

  • 选用一个 R=26 的字母表 , 涵盖小写字母(这个选择会影响后面代码写下标);
  • 注意这个说法索引值,和后面的数组下标是 不同 的,这个代码容易出错就是下标和索引值的对应关系没搞明白;
索引值 字母
0 a
1 b
…. …
18 s
19 t
…. …
25 z

待排序的字符串

she
sells
seashells
by
the
sea
shore
the
shells
she
sells
are
surely
seashells

逐行代码解释

代码的大框架

  • ★ 标记的注释是需要仔细区分的盲点
    // 算法启动
    public static void sort(String[] a) {
        // 输入一个字符串数组 a 获取字符串数组的长度(即待排序的字符串个数)
        int n = a.length;

        // 声明一个备用字符串数组aux 用于排序时回写
        String[] aux = new String[n];

        // 启动递归排序 初始排序长度涵盖全部字符串[0,n-1]
        // aux作为参数传入,相当于一个全局变量,aux只声明了一次 ★
        sort(a, 0, n-1, 0, aux);
    }


    // 将字符串数组从 [lo,hi]的元素a[i] 按照 第d个字母 排序
    private static void sort(String[] a, int lo, int hi, int d, String[] aux) {

        // 函数局部变量,每次sort 都会重新创建一个count[]数组 ★
        // 注意cout[]的长度为R+2 ★
        int[] count = new int[R+2];

        // 计算频率
        for (int i = lo; i <= hi; i++) { }
        // 频率转换成索引
        for (int r = 0; r < R+1; r++) { }
        // 数据分布
        for (int i = lo; i <= hi; i++) { }
        // 回写
        for (int i = lo; i <= hi; i++) { }
        // 递归排序
        for (int r = 0; r < R; r++) { }

    }

频率计算

MSD

        // 频率计算
        int[] count = new int[R+2];
        for (int i = lo; i <= hi; i++) {
            int c = charAt(a[i], d);
            count[c+2]++;
        }

解释

        // 频率计算
        // 1. count数组的作用是记录每个字母出现的频率(就是出现次数)
        // 2. 把长度声明成 R+2 ;
        //    R 个位置用来放对应字母的出现次数
        //    1 个位置用来应对达到字符串结尾
        //    1 个位置是用于后面转化为索引 ★(下个标题说明)
        int[] count = new int[R+2];

        // for是一个从lo到hi的循环,就是遍历要排序的那些字符串,可能这一波排这5个字符串,
        // 可能这一波排那3个字符串,实现只关注 子字符串数组 的效果;
        for (
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值