《算法》第五章部分程序 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 }

原文地址:https://www.cnblogs.com/cuancuancuanhao/p/9869279.html

时间: 2024-08-04 21:32:28

《算法》第五章部分程序 part 3的相关文章

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

? 书中第五章部分程序,包括在加上自己补充的代码,Trie 树类,Trie 集合,三值搜索树(Ternary Search Trie) ● Trie 树类 1 package package01; 2 3 import edu.princeton.cs.algs4.StdIn; 4 import edu.princeton.cs.algs4.StdOut; 5 import edu.princeton.cs.algs4.Queue; 6 7 public class class01<Value>

《算法》第五章部分程序 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_BY

《算法》第五章部分程序 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

Gradle 1.12用户指南翻译——第四十五章. 应用程序插件

文由CSDN博客貌似掉线翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://github.com/msdx/gradledoc 本文翻译所在分支: https://github.com/msdx/gradledoc/tree/1.12. 直接浏览双语版的文档请访问: http://gradledoc.qiniudn.com/1.12/usergu

《算法》第一章部分程序

? 书中第一章部分程序,加上自己补充的代码.包括若干种二分搜索和寻找图上连通分量数的两种算法. ● 代码,二分搜索 1 package package01; 2 3 import java.util.Arrays; 4 import edu.princeton.cs.algs4.StdRandom; 5 6 public class class01 7 { 8 public int binarySearch(int [] a, int target) // 非递归实现 9 { 10 int lp

第五章 C程序结构

一.数值类型 1.实数常量的表示:3.5(双精度),3.5f(单精度),3.5L(长双精度) 2.整数常量:char字符常量('a','b','0')当做一个整型常量参加运算 3.数字字符与英文字母字符的编号(Ascll码)都是顺序连接的 二.控制语句 1.while和do while的区别:当while条件不成立时,while()循环不执行循环语句,而do while会循环执行一次循环语句再判断 2.流程控制语句:continue(中断本次循环)    break(跳出整个循环) 3.开关语句

算法第五章小结

一.回溯算法的概念以及理解 概念:回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标. 理解:在回溯法中,每次扩大当前部分解时,都面临一个可选的状态集合,新的部分解就通过在该集合中选择构造而成.这样的状态集合,其结构是一棵多叉树,每个树结点代表一个可能的部分解,它的儿子是在它的基础上生成的其他部分解.树根为初始状态,这样的状态集合称为状态空间树. 二.“子集和”问题的解空间结构和约束函数 1.解空间结构 非负非零的整数集合 S = {x1, x2, …, xn}

算法第五章上机实践报告

一 . 实践题目 7-2 工作分配问题 二 . 问题描述 设有n件工作分配给n个人.将工作i分配给第j个人所需的费用为cij . 设计一个算法,对于给定的工作费用,为每一个人都分配1 件不同的工作,并使总费用达到最小. 输入格式: 输入数据的第一行有1 个正整数n (1≤n≤20).接下来的n行,每行n个数,表示工作费用. 输出格式: 将计算出的最小总费用输出到屏幕. 输入样例: 3 10 2 3 2 3 4 3 4 5 输出样例: 9 三 . 算法描述 1. 解空间 第一个人选择第几个工作,第

算法第五章 | 回溯算法

一. 回溯算法 回溯法有"通用的解题法"之称.可以系统地搜索一个问题的所有解或任一解,是一个既带有系统性又带有跳跃性的搜索算法. 它在问题的解空间树中,按深度优先策略,从根节点出发搜索解空间树.算法搜索至解空间树的任一结点时,先判断该结点是否包含问题的解.如果肯定不包含,则跳过对以该结点为根的子树的搜索,逐层向其祖先结点回溯.否则,进入该子树,继续按深度优先策略搜索.回溯法求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束.回溯法求问题的一个解时,只要搜索到问题的一个解