《算法》第五章部分程序 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的主要内容,如果未能解决你的问题,请参考以下文章