《算法》第五章部分程序 part 3
Posted cuancuancuanhao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《算法》第五章部分程序 part 3相关的知识,希望对你有一定的参考价值。
? 书中第五章部分程序,包括在加上自己补充的代码,字符串高位优先排序(美国国旗排序)
● 美国国旗排序
1 package package01; 2 3 import edu.princeton.cs.algs4.StdIn; 4 import edu.princeton.cs.algs4.StdOut; 5 import edu.princeton.cs.algs4.Stack; 6 7 public class class01 8 { 9 private static final int BITS_PER_BYTE = 8; 10 private static final int BITS_PER_INT = 32; 11 private static final int R = 256; 12 private static final int CUTOFF = 15; 13 14 private class01() {} 15 16 public static void sort(String[] a) 17 { 18 sortKernel(a, 0, a.length - 1); 19 } 20 21 public static void sortKernel(String[] a, int lo, int hi) 22 { 23 Stack<Integer> st = new Stack<Integer>(); 24 int[] first = new int[R + 2], next = new int[R + 2]; 25 int d = 0; 26 for (st.push(lo), st.push(hi), st.push(d); !st.isEmpty();) 27 { 28 d = st.pop(); hi = st.pop(); lo = st.pop(); 29 if (hi <= lo + CUTOFF) 30 { 31 insertion(a, lo, hi, d); 32 continue; 33 } 34 for (int i = lo; i <= hi; i++) // 以字符串的第 d 位进行统计 35 first[charAt(a[i], d) + 2]++; 36 first[0] = lo; // 前部垫起 37 for (int c = 0; c <= R; c++) // 前缀和与子问题分配 38 { 39 first[c + 1] += first[c]; 40 if (c > 0 && first[c + 1] - 1 > first[c]) // 存在至少 2 个第 d 位为 c 的字符串,注意排除 c == 0 的情况 41 { 42 st.push(first[c]); // 添加子问题,对第 d 位为 c 的所有字符串关于第 d+1 位进行排序 43 st.push(first[c + 1] - 1); 44 st.push(d + 1); 45 } 46 } 47 for (int c = 0; c < R + 2; c++) // 拷贝 first 到 next 中,next 用于搬运字符串过程中的变化索引 48 next[c] = first[c]; 49 for (int k = lo; k <= hi; k++) // 搬运字符串到指定位置,循环将 a[k] 作为交换的临时位置 50 { 51 int c = charAt(a[k], d) + 1; // 取 a[k] 的第 d 位的下一个字符 52 for (; first[c] > k; c = charAt(a[k], d) + 1) // 只要 c 出现的位置排在 k 后面,就交换 a[k] 和 a[next[c]],并且 next[c]向后移一个位置 53 exch(a, k, next[c]++); 54 next[c]++; // 全部移完了,next[c] 再自增 1,表示 c 开头的索引已经等于 first[c+1],避免重复排序 55 } 56 for (int c = 0; c < R + 2; c++) // 清除 first 和 next 57 first[c] = next[c] = 0; 58 } 59 } 60 61 private static void insertion(String[] a, int lo, int hi, int d) 62 { 63 for (int i = lo; i <= hi; i++) 64 { 65 for (int j = i; j > lo && less(a[j], a[j - 1], d); j--) 66 exch(a, j, j - 1); 67 } 68 } 69 70 private static int charAt(String s, int d) 71 { 72 assert d >= 0 && d <= s.length(); 73 if (d == s.length()) 74 return -1; 75 return s.charAt(d); 76 } 77 78 private static void exch(String[] a, int i, int j) 79 { 80 String temp = a[i]; 81 a[i] = a[j]; 82 a[j] = temp; 83 } 84 85 private static boolean less(String v, String w, int d) 86 { 87 assert v.substring(0, d).equals(w.substring(0, d)); 88 for (int i = d; i < Math.min(v.length(), w.length()); i++) 89 { 90 if (v.charAt(i) == w.charAt(i)) 91 continue; 92 return v.charAt(i) < w.charAt(i); 93 } 94 return v.length() < w.length(); 95 } 96 97 public static void sort(int[] a) // 数组排序 98 { 99 sortKernel(a, 0, a.length - 1); 100 } 101 102 private static void sortKernel(int[] a, int lo, int hi) 103 { 104 Stack<Integer> st = new Stack<Integer>(); 105 int[] first = new int[R + 1], next = new int[R + 1]; 106 int mask = R - 1, d = 0; 107 for (st.push(lo), st.push(hi), st.push(d); !st.isEmpty();) 108 { 109 d = st.pop(); hi = st.pop(); lo = st.pop(); 110 if (hi <= lo + CUTOFF) 111 { 112 insertion(a, lo, hi, d); 113 continue; 114 } 115 int shift = BITS_PER_INT - BITS_PER_BYTE * (d + 1); // 取从左往右的第 d 字节 116 for (int i = lo; i <= hi; i++) 117 first[((a[i] >> shift) & mask) + 1]++; 118 first[0] = lo; 119 for (int c = 0; c < R; c++) 120 { 121 first[c + 1] += first[c]; 122 if (d < 3 && first[c + 1] - 1 > first[c]) // c > 0 条件改为,当前字节不是最低字节 123 { 124 st.push(first[c]); 125 st.push(first[c + 1] - 1); 126 st.push(d + 1); 127 } 128 } 129 for (int c = 0; c < R + 1; c++) 130 next[c] = first[c]; 131 for (int k = lo; k <= hi; k++) 132 { 133 int c = (a[k] >> shift) & mask; 134 for (; first[c] > k; c = (a[k] >> shift) & mask) 135 exch(a, k, next[c]++); 136 next[c]++; 137 } 138 for (int c = 0; c < R + 1; c++) 139 first[c] = next[c] = 0; 140 } 141 } 142 143 private static void insertion(int[] a, int lo, int hi, int d) 144 { 145 for (int i = lo; i <= hi; i++) 146 { 147 for (int j = i; j > lo && less(a[j], a[j - 1], d); j--) 148 exch(a, j, j - 1); 149 } 150 } 151 152 private static void exch(int[] a, int i, int j) 153 { 154 int temp = a[i]; 155 a[i] = a[j]; 156 a[j] = temp; 157 } 158 159 private static boolean less(int v, int w, int d) 160 { 161 int mask = R - 1; 162 for (int i = d; i < 4; i++) 163 { 164 int shift = BITS_PER_INT - BITS_PER_BYTE * (i + 1); 165 int a = (v >> shift) & mask, b = (w >> shift) & mask; 166 if (a == b) 167 continue; 168 return a < b; 169 } 170 return false; 171 } 172 173 public static void main(String[] args) 174 { 175 if (args.length > 0 && args[0].equals("int")) 176 { 177 int[] a = StdIn.readAllInts(); 178 sort(a); 179 180 for (int i = 0; i < a.length; i++) 181 StdOut.println(a[i]); 182 } 183 else 184 { 185 String[] a = StdIn.readAllStrings(); 186 sort(a); 187 188 for (int i = 0; i < a.length; i++) 189 StdOut.println(a[i]); 190 } 191 } 192 }
● 美国国旗排序 2
1 package package01; 2 3 import edu.princeton.cs.algs4.StdIn; 4 import edu.princeton.cs.algs4.StdOut; 5 import edu.princeton.cs.algs4.Stack; 6 7 public class class01 8 { 9 private static final int R = 256; 10 private static final int CUTOFF = 15; 11 12 private class01() {} 13 14 public static void sort(String[] a) 15 { 16 sortKernel(a, 0, a.length - 1); 17 } 18 19 public static void sortKernel(String[] a, int lo, int hi) 20 { 21 Stack<Integer> st = new Stack<Integer>(); 22 int[] count = new int[R + 1]; 23 int d = 0; 24 for (st.push(lo), st.push(hi), st.push(d); !st.isEmpty();) 25 { 26 d = st.pop(); hi = st.pop(); lo = st.pop(); 27 if (hi <= lo + CUTOFF) 28 { 29 insertion(a, lo, hi, d); 30 continue; 31 } 32 for (int i = lo; i <= hi; i++) 33 count[charAt(a[i], d) + 1]++; 34 count[0] += lo; 35 for (int c = 0; c < R; c++) 36 { 37 count[c + 1] += count[c]; // count[c] 表示键值不大于 c 的元素个数(相当于字符 c+1 起始位置先前 1 格) 38 if (c > 0 && count[c + 1] - 1 > count[c]) 39 { 40 st.push(count[c]); 41 st.push(count[c + 1] - 1); 42 st.push(d + 1); 43 } 44 } 45 for (int r = hi; r >= lo; r--) // r 从后向前 46 { 47 int c = charAt(a[r], d) + 1; 48 for (; r >= lo && count[c] - 1 <= r;) 49 { 50 if (count[c] - 1 == r) 51 count[c]--; 52 r--; 53 if (r >= lo) 54 c = charAt(a[r], d) + 1; 55 } 56 if (r < lo) // r 已经降到 lo 以下,调整完成 57 break; 58 for (count[c]--; count[c] != r; c = charAt(a[r], d) + 1, count[c]--) 59 exch(a, r, count[c]); 60 } 61 } 62 for (int c = 0; c < R + 1; c++) // 清除 count 63 count[c] = 0; 64 } 65 66 private static void insertion(String[] a, int lo, int hi, int d) 67 { 68 for (int i = lo; i <= hi; i++) 69 { 70 for (int j = i; j > lo && less(a[j], a[j - 1], d); j--) 71 exch(a, j, j - 1); 72 } 73 } 74 75 private static int charAt(String s, int d) 76 { 77 assert d >= 0 && d <= s.length(); 78 if (d == s.length()) 79 return -1; 80 return s.charAt(d); 81 } 82 83 private static void exch(String[] a, int i, int j) 84 { 85 String temp = a[i]; 86 a[i] = a[j]; 87 a[j] = temp; 88 } 89 90 private static boolean less(String v, String w, int d) 91 { 92 assert v.substring(0, d).equals(w.substring(0, d)); 93 for (int i = d; i < Math.min(v.length(), w.length()); i++) 94 { 95 if (v.charAt(i) == w.charAt(i)) 96 continue; 97 return v.charAt(i) < w.charAt(i); 98 } 99 return v.length() < w.length(); 100 } 101 102 public static void main(String[] args) 103 { 104 String[] a = StdIn.readAllStrings(); 105 sort(a); 106 107 for (int i = 0; i < a.length; i++) 108 StdOut.println(a[i]); 109 } 110 }
以上是关于《算法》第五章部分程序 part 3的主要内容,如果未能解决你的问题,请参考以下文章