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

Posted cuancuancuanhao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《算法》第五章部分程序 part 2相关的知识,希望对你有一定的参考价值。

? 书中第五章部分程序,包括在加上自己补充的代码,字符串高位优先排序(计数 + 插排),(原地排序),(三路快排,与前面的三路归并排序相同)

● 计数 + 插排

  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     private static final int BITS_PER_INT = 32;
 10     private static final int R = 256;
 11     private static final int CUTOFF = 15;   // 尺寸不超过 CUTOFF 的数组使用插入排序
 12 
 13     private class01() {}
 14 
 15     public static void sort(String[] a)     // 对字符串的排序
 16     {
 17         int n = a.length;
 18         String[] aux = new String[n];
 19         sortKernel(a, 0, n - 1, 0, aux);
 20     }
 21 
 22     private static void sortKernel(String[] a, int lo, int hi, int d, String[] aux)
 23     {
 24         if (hi <= lo + CUTOFF)              // 数组较小,使用插入排序
 25         {
 26             insertion(a, lo, hi, d);
 27             return;
 28         }
 29         int[] count = new int[R + 2];
 30         for (int i = lo; i <= hi; i++)
 31             count[charAt(a[i], d) + 2]++;
 32         for (int r = 0; r < R + 1; r++)
 33             count[r + 1] += count[r];
 34         for (int i = lo; i <= hi; i++)
 35             aux[count[charAt(a[i], d) + 1]++] = a[i];
 36         for (int i = lo; i <= hi; i++)      // 写回时注意偏移
 37             a[i] = aux[i - lo];
 38         for (int r = 0; r < R; r++)         // 每个字母开头的子数组分别排序
 39             sortKernel(a, lo + count[r], lo + count[r + 1] - 1, d + 1, aux);
 40     }
 41 
 42     private static void insertion(String[] a, int lo, int hi, int d)    // 数组 a 关于第 d 位插入排序
 43     {
 44         for (int i = lo; i <= hi; i++)
 45         {
 46             for (int j = i; j > lo && less(a[j], a[j - 1], d); j--)
 47                 exch(a, j, j - 1);
 48         }
 49     }
 50 
 51     private static void exch(String[] a, int i, int j)
 52     {
 53         String temp = a[i];
 54         a[i] = a[j];
 55         a[j] = temp;
 56     }
 57 
 58     private static int charAt(String s, int d)              // 按索引取字符串的字符
 59     {
 60         assert d >= 0 && d <= s.length();
 61         if (d == s.length())
 62             return -1;
 63         return s.charAt(d);
 64     }
 65 
 66     private static boolean less(String v, String w, int d)
 67     {
 68         //assert v.substring(0, d).equals(w.substring(0, d)); // 先检查等于
 69         for (int i = d; i < Math.min(v.length(), w.length()); i++)
 70         {
 71             if (v.charAt(i) < w.charAt(i))
 72                 return true;
 73             if (v.charAt(i) > w.charAt(i))
 74                 return false;
 75         }
 76         return v.length() < w.length();
 77     }
 78 
 79     public static void sort(int[] a)        // 对数组的排序
 80     {
 81         int n = a.length;
 82         int[] aux = new int[n];
 83         sortKernel(a, 0, n - 1, 0, aux);
 84     }
 85 
 86     private static void sortKernel(int[] a, int lo, int hi, int d, int[] aux)
 87     {
 88         if (hi <= lo + CUTOFF)
 89         {
 90             insertion(a, lo, hi, d);
 91             return;
 92         }
 93         int[] count = new int[R + 1];
 94         int mask = R - 1;
 95         int shift = BITS_PER_INT - BITS_PER_BYTE * d - BITS_PER_BYTE;
 96         for (int i = lo; i <= hi; i++)
 97         {
 98             int c = (a[i] >> shift) & mask;
 99             count[c + 1]++;
100         }
101         for (int r = 0; r < R; r++)
102             count[r + 1] += count[r];
103         if (d == 0)                         // 符号位,0x00-0x7F 要排在 0x80-0xFF 的后面
104         {
105             int shift1 = count[R] - count[R / 2];
106             int shift2 = count[R / 2];
107             for (int r = 0; r < R / 2; r++)
108                 count[r] += shift1;
109             for (int r = R / 2; r < R; r++)
110                 count[r] -= shift2;
111         }
112         for (int i = lo; i <= hi; i++)
113         {
114             int c = (a[i] >> shift) & mask;
115             aux[count[c]++] = a[i];
116         }
117         for (int i = lo; i <= hi; i++)
118             a[i] = aux[i - lo];
119         if (d == 4)                         // 已经到了最高位,不用分治了
120             return;
121         if (count[0] > 0)
122             sortKernel(a, lo, lo + count[0] - 1, d + 1, aux);
123         for (int r = 0; r < R; r++)
124         {
125             if (count[r + 1] > count[r])    // 存在数字第 d 位是 r 的数字需要排序
126                 sortKernel(a, lo + count[r], lo + count[r + 1] - 1, d + 1, aux);
127         }
128     }
129 
130     private static void insertion(int[] a, int lo, int hi, int d)
131     {
132         for (int i = lo; i <= hi; i++)
133         {
134             for (int j = i; j > lo && a[j] < a[j - 1]; j--)
135                 exch(a, j, j - 1);
136         }
137     }
138 
139     private static void exch(int[] a, int i, int j)
140     {
141         int temp = a[i];
142         a[i] = a[j];
143         a[j] = temp;
144     }
145 
146     public static void main(String[] args)
147     {
148         String[] a = StdIn.readAllStrings();
149         int n = a.length;
150         sort(a);
151         for (int i = 0; i < n; i++)
152             StdOut.println(a[i]);
153     }
154 }

● 原地排序

 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 R = 256;
 9     private static final int CUTOFF = 0;
10 
11     private class01() {}
12 
13     public static void sort(String[] a)
14     {
15         int n = a.length;
16         sortKernel(a, 0, n - 1, 0);
17     }
18 
19     private static void sortKernel(String[] a, int lo, int hi, int d)
20     {
21         if (hi <= lo + CUTOFF)
22         {
23             insertion(a, lo, hi, d);
24             return;
25         }
26         int[] heads = new int[R + 2];       // 需要记录每个字符出现的首位和末位
27         int[] tails = new int[R + 1];
28         for (int i = lo; i <= hi; i++)
29             heads[charAt(a[i], d) + 2]++;
30         heads[0] = lo;                      // heads 首位设为 lo,方便直接做 a 的索引
31         for (int r = 0; r < R + 1; r++)
32         {
33             heads[r + 1] += heads[r];
34             tails[r] = heads[r + 1];        // tails 等于前缀和的 heads 左移一格,等于下一个字符出现的位置
35         }
36         for (int r = 0; r < R + 1; r++)     // 循环完成所有字符
37         {
38             for (; heads[r] < tails[r]; heads[r]++)     // 循环直到所有 heads 向 tails 靠拢
39             {
40                 // a[heads[r]] 作为临时位置,每次把其上字符串发送到排序后正确的位置上,替换下来的字符串放回,用于下一次发送
41                 for (int c = charAt(a[heads[r]], d); c + 1 != r; c = charAt(a[heads[r]], d))
42                     exch(a, heads[r], heads[c + 1]++);  // 每次发送后要后移同一字符串的目标位置
43             }
44         }
45         for (int r = 0; r < R; r++)                     // 分治所有子数组
46             sortKernel(a, tails[r], tails[r + 1] - 1, d + 1);
47     }
48 
49     private static void insertion(String[] a, int lo, int hi, int d)
50     {
51         for (int i = lo; i <= hi; i++)
52         {
53             for (int j = i; j > lo && less(a[j], a[j - 1], d); j--)
54                 exch(a, j, j - 1);
55         }
56     }
57 
58     private static void exch(String[] a, int i, int j)
59     {
60         String temp = a[i];
61         a[i] = a[j];
62         a[j] = temp;
63     }
64 
65     private static int charAt(String s, int d)
66     {
67         assert d >= 0 && d <= s.length();
68         if (d == s.length())
69             return -1;
70         return s.charAt(d);
71     }
72 
73     private static boolean less(String v, String w, int d)
74     {
75         // assert v.substring(0, d).equals(w.substring(0, d));
76         for (int i = d; i < Math.min(v.length(), w.length()); i++)
77         {
78             if (v.charAt(i) < w.charAt(i))
79                 return true;
80             if (v.charAt(i) > w.charAt(i))
81                 return false;
82         }
83         return v.length() < w.length();
84     }
85 
86     public static void main(String[] args)
87     {
88         String[] a = StdIn.readAllStrings();
89         int n = a.length;
90         sort(a);
91         for (int i = 0; i < n; i++)
92             StdOut.println(a[i]);
93     }
94 }

● 三路快排

 1 package package01;
 2 
 3 import edu.princeton.cs.algs4.StdIn;
 4 import edu.princeton.cs.algs4.StdOut;
 5 import edu.princeton.cs.algs4.StdRandom;
 6 
 7 public class class01
 8 {
 9     private static final int CUTOFF = 15;
10 
11     private class01() {}
12 
13     public static void sort(String[] a)
14     {
15         StdRandom.shuffle(a);
16         sortKernel(a, 0, a.length - 1, 0);
17     }
18 
19     private static void sortKernel(String[] a, int lo, int hi, int d)
20     {
21         if (hi <= lo + CUTOFF)
22         {
23             insertion(a, lo, hi, d);
24             return;
25         }
26         int lt = lo, gt = hi;
27         int v = charAt(a[lo], d);
28         for (int i = lo + 1; i <= gt;)
29         {
30             int t = charAt(a[i], d);
31             if (t < v)
32                 exch(a, lt++, i++);
33             else if (t > v)
34                 exch(a, i, gt--);
35             else
36                 i++;
37         }
38         sortKernel(a, lo, lt - 1, d);
39         if (v >= 0)
40             sortKernel(a, lt, gt, d + 1);
41         sortKernel(a, gt + 1, hi, d);
42     }
43 
44     private static void insertion(String[] a, int lo, int hi, int d)
45     {
46         for (int i = lo; i <= hi; i++)
47         {
48             for (int j = i; j > lo && less(a[j], a[j - 1], d); j--)
49                 exch(a, j, j - 1);
50         }
51     }
52 
53     private static boolean less(String v, String w, int d)
54     {
55         assert v.substring(0, d).equals(w.substring(0, d));
56         for (int i = d; i < Math.min(v.length(), w.length()); i++)
57         {
58             if (v.charAt(i) < w.charAt(i))
59                 return true;
60             if (v.charAt(i) > w.charAt(i))
61                 return false;
62         }
63         return v.length() < w.length();
64     }
65 
66     private static int charAt(String s, int d)
67     {
68         assert d >= 0 && d <= s.length();
69         if (d == s.length())
70             return -1;
71         return s.charAt(d);
72     }
73 
74     private static void exch(String[] a, int i, int j)
75     {
76         String temp = a[i];
77         a[i] = a[j];
78         a[j] = temp;
79     }
80 
81     public static void main(String[] args)
82     {
83         String[] a = StdIn.readAllStrings();
84         int n = a.length;
85 
86         sort(a);
87 
88         for (int i = 0; i < n; i++)
89             StdOut.println(a[i]);
90     }
91 }

 

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

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

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

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

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

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

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