《算法》第五章部分程序 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("\n<Constructor> repeated character = ‘" + c + "‘.\n");
 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("\n<toIndex> c >= inverse.length || inverse[c] == -1.\n");
 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("\n<toChar> index < 0 || index >= R.\n");
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 : "\n<main> Strings not fixed length.\n";
78
79         sort(a, w);
80
81         for (int i = 0; i < n; i++)
82             StdOut.println(a[i]);
83     }
84 }

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

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

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

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

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. 解空间 第一个人选择第几个工作,第

算法第五章 | 回溯算法

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