《算法》第五章部分程序 part 1

Posted cuancuancuanhao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《算法》第五章部分程序 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 }

 

以上是关于《算法》第五章部分程序 part 1的主要内容,如果未能解决你的问题,请参考以下文章

《算法》第五章部分程序 part 3

《算法》第五章部分程序 part 4

ROS机器人程序设计(原书第2版)补充资料 (伍) 第五章 计算机视觉

[XJTUSE 算法设计与分析] 第五章 回溯法

python程序设计基础(嵩天)第五章课后习题部分答案

机器学习算法概述第五章——CART算法