zoukankan      html  css  js  c++  java
  • 《算法》第五章部分程序 part 1

    ▶ 书中第五章部分程序,包括在加上自己补充的代码,字母表类,字符串低位优先排序(桶排)

    ● 字母表类

      1 package package01;
      2 
      3 import edu.princeton.cs.algs4.StdOut;
      4 
      5 public class class01
      6 {
      7     public static final class01 BINARY = new class01("01");
      8 
      9     public static final class01 OCTAL = new class01("01234567");
     10 
     11     public static final class01 DECIMAL = new class01("0123456789");
     12 
     13     public static final class01 HEXADECIMAL = new class01("0123456789ABCDEF");
     14 
     15     public static final class01 DNA = new class01("ACGT");
     16 
     17     public static final class01 LOWERCASE = new class01("abcdefghijklmnopqrstuvwxyz");
     18 
     19     public static final class01 UPPERCASE = new class01("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
     20 
     21     public static final class01 PROTEIN = new class01("ACDEFGHIKLMNPQRSTVWY");// 蛋白质?
     22 
     23     public static final class01 BASE64 = new class01("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
     24 
     25     public static final class01 ASCII = new class01(128);
     26 
     27     public static final class01 EXTENDED_ASCII = new class01(256);
     28 
     29     public static final class01 UNICODE16 = new class01(65536);
     30 
     31     private char[] alphabet;        // 索引 -> 字母
     32     private int[] inverse;          // 字母 -> 索引
     33     private final int R;            // 字母表基数
     34 
     35     public class01(String alpha)    // 从字符串生成一个字母表
     36     {
     37         boolean[] unicode = new boolean[Character.MAX_VALUE];   // 检查输入字符串是否有重复字母
     38         for (int i = 0; i < alpha.length(); i++)
     39         {
     40             char c = alpha.charAt(i);
     41             if (unicode[c])
     42                 throw new IllegalArgumentException("
    <Constructor> repeated character = '" + c + "'.
    ");
     43             unicode[c] = true;
     44         }
     45         alphabet = alpha.toCharArray();
     46         R = alpha.length();
     47         inverse = new int[Character.MAX_VALUE];
     48         for (int i = 0; i < inverse.length; i++)
     49             inverse[i] = -1;
     50         for (int c = 0; c < R; c++)
     51             inverse[alphabet[c]] = c;
     52     }
     53 
     54     private class01(int radix)      // 从基数生成一个字母表
     55     {
     56         R = radix;
     57         alphabet = new char[R];
     58         inverse = new int[R];
     59         for (int i = 0; i < R; i++) // 正反向都初始化为 0 ~ R-1
     60             alphabet[i] = (char)i;
     61         for (int i = 0; i < R; i++)
     62             inverse[i] = i;
     63     }
     64 
     65     public class01()                //  默认构造扩展 aSCII
     66     {
     67         this(256);
     68     }
     69 
     70     public boolean contains(char c)
     71     {
     72         return inverse[c] != -1;
     73     }
     74 
     75     public int radix()
     76     {
     77         return R;
     78     }
     79 
     80     public int lgR()                // 表示字母表所需要的二进制位数
     81     {
     82         int lgR = 0;
     83         for (int t = R - 1; t > 0; t <<= 1)
     84             lgR++;
     85         return lgR;
     86     }
     87 
     88     public int toIndex(char c)      // 字符转索引
     89     {
     90         if (c >= inverse.length || inverse[c] == -1)
     91             throw new IllegalArgumentException("
    <toIndex> c >= inverse.length || inverse[c] == -1.
    ");
     92         return inverse[c];
     93     }
     94 
     95     public int[] toIndices(String s)        // 字符串转数组
     96     {
     97         char[] source = s.toCharArray();
     98         int[] target = new int[s.length()];
     99         for (int i = 0; i < source.length; i++)
    100             target[i] = toIndex(source[i]);
    101         return target;
    102     }
    103 
    104     public char toChar(int index)
    105     {
    106         if (index < 0 || index >= R)
    107             throw new IllegalArgumentException("
    <toChar> index < 0 || index >= R.
    ");
    108         return alphabet[index];
    109     }
    110 
    111     public String toChars(int[] indices)    // 数组转字符串
    112     {
    113         StringBuilder s = new StringBuilder(indices.length); // 使用 StringBuilder 类,防止平方级时间消耗
    114         for (int i = 0; i < indices.length; i++)
    115             s.append(toChar(indices[i]));
    116         return s.toString();
    117     }
    118 
    119     public static void main(String[] args)
    120     {
    121         int[]  encoded1 = class01.BASE64.toIndices("NowIsTheTimeForAllGoodMen");
    122         String decoded1 = class01.BASE64.toChars(encoded1);
    123         StdOut.println(decoded1);
    124 
    125         int[]  encoded2 = class01.DNA.toIndices("AACGAACGGTTTACCCCG");
    126         String decoded2 = class01.DNA.toChars(encoded2);
    127         StdOut.println(decoded2);
    128 
    129         int[]  encoded3 = class01.DECIMAL.toIndices("01234567890123456789");
    130         String decoded3 = class01.DECIMAL.toChars(encoded3);
    131         StdOut.println(decoded3);
    132     }
    133 }

    ● 字符串低位优先排序(桶排)

     1 package package01;
     2 
     3 import edu.princeton.cs.algs4.StdIn;
     4 import edu.princeton.cs.algs4.StdOut;
     5 
     6 public class class01
     7 {
     8     private static final int BITS_PER_BYTE = 8;
     9 
    10     private class01() { }
    11 
    12     public static void sort(String[] a, int w)  // 每个字符串定长 w 的字符串数组排序
    13     {
    14         int n = a.length;
    15         int R = 256;                            // 默认基数
    16         String[] aux = new String[n];
    17 
    18         for (int d = w - 1; d >= 0; d--)        // 从最后一位起,每次循环处理一位
    19         {
    20             int[] count = new int[R + 1];
    21             for (int i = 0; i < n; i++)         // 桶计数,这里 count[0] 和 count [1] 暂时为 0
    22                 count[a[i].charAt(d) + 1]++;
    23             for (int r = 0; r < R; r++)         // 规约前缀和,完成后字母 c 在排序中的起始下标是 count[toIndex[c]],count[0] 固定为 0
    24                 count[r + 1] += count[r];
    25             for (int i = 0; i < n; i++)         // 向临时数组 aux 写入数据
    26                 aux[count[a[i].charAt(d)]++] = a[i];
    27             for (int i = 0; i < n; i++)         // 排序完成的数组写回原数组
    28                 a[i] = aux[i];
    29         }
    30     }
    31 
    32     public static void sort(int[] a)            // 有符号数组排序,以一个 Byte 为键
    33     {
    34         final int BITS = 32;                    // int 类型占 256 Bit
    35         final int R = 1 << BITS_PER_BYTE;       // 每个 Byte 表示 0 ~ 255
    36         final int MASK = R - 1;                 // 0xFF,用于只保留最低位的蒙版
    37         final int w = BITS / BITS_PER_BYTE;     // int 类型占 4 Byte
    38 
    39         int n = a.length;
    40         int[] aux = new int[n];
    41         for (int d = 0; d < w; d++)
    42         {
    43             int[] count = new int[R + 1];
    44             for (int i = 0; i < n; i++)
    45             {
    46                 int c = (a[i] >> BITS_PER_BYTE * d) & MASK; // 保留从右往左数第 d 个 Byte
    47                 count[c + 1]++;
    48             }
    49             for (int r = 0; r < R; r++)
    50                 count[r + 1] += count[r];
    51             if (d == w - 1)                                 // 符号位,0x00-0x7F 要排在 0x80-0xFF 的后面
    52             {
    53                 int shift1 = count[R] - count[R / 2];       // 低半段(正值)移到后面
    54                 int shift2 = count[R / 2];
    55                 for (int r = 0; r < R / 2; r++)
    56                     count[r] += shift1;
    57                 for (int r = R / 2; r < R; r++)             // 高半段(负值)移到前面
    58                     count[r] -= shift2;
    59             }
    60             for (int i = 0; i < n; i++)
    61             {
    62                 int c = (a[i] >> BITS_PER_BYTE * d) & MASK;
    63                 aux[count[c]++] = a[i];
    64             }
    65             for (int i = 0; i < n; i++)
    66                 a[i] = aux[i];
    67         }
    68     }
    69 
    70     public static void main(String[] args)
    71     {
    72         String[] a = StdIn.readAllStrings();
    73         int n = a.length;
    74 
    75         int w = a[0].length();      // 检查字符串是否定长
    76         for (int i = 0; i < n; i++)
    77             assert a[i].length() == w : "
    <main> Strings not fixed length.
    ";
    78 
    79         sort(a, w);
    80 
    81         for (int i = 0; i < n; i++)
    82             StdOut.println(a[i]);
    83     }
    84 }
  • 相关阅读:
    你看,那个人好像一条狗哎
    我竟然被抓去做了比特币挖矿工
    聊聊JAVA中 String类为什么不可变
    三分钟深入TT猫之故障转移
    shell实现两个数的相加
    shell截取字符串的方法
    Vi命令:如何删除全部内容?
    bash中不可以用字符串做数组下标
    awk打印出当前行的上一行
    awk同时处理多个文件
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/9869242.html
Copyright © 2011-2022 走看看