▶ 书中第五章部分程序,包括在加上自己补充的代码,字母表类,字符串低位优先排序(桶排)

● 字母表类

 package package01;

 import edu.princeton.cs.algs4.StdOut;

 public class class01
{
public static final class01 BINARY = new class01("01"); public static final class01 OCTAL = new class01("01234567"); public static final class01 DECIMAL = new class01("0123456789"); public static final class01 HEXADECIMAL = new class01("0123456789ABCDEF"); public static final class01 DNA = new class01("ACGT"); public static final class01 LOWERCASE = new class01("abcdefghijklmnopqrstuvwxyz"); public static final class01 UPPERCASE = new class01("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); public static final class01 PROTEIN = new class01("ACDEFGHIKLMNPQRSTVWY");// 蛋白质? public static final class01 BASE64 = new class01("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); public static final class01 ASCII = new class01(128); public static final class01 EXTENDED_ASCII = new class01(256); public static final class01 UNICODE16 = new class01(65536); private char[] alphabet; // 索引 -> 字母
private int[] inverse; // 字母 -> 索引
private final int R; // 字母表基数 public class01(String alpha) // 从字符串生成一个字母表
{
boolean[] unicode = new boolean[Character.MAX_VALUE]; // 检查输入字符串是否有重复字母
for (int i = 0; i < alpha.length(); i++)
{
char c = alpha.charAt(i);
if (unicode[c])
throw new IllegalArgumentException("\n<Constructor> repeated character = '" + c + "'.\n");
unicode[c] = true;
}
alphabet = alpha.toCharArray();
R = alpha.length();
inverse = new int[Character.MAX_VALUE];
for (int i = 0; i < inverse.length; i++)
inverse[i] = -1;
for (int c = 0; c < R; c++)
inverse[alphabet[c]] = c;
} private class01(int radix) // 从基数生成一个字母表
{
R = radix;
alphabet = new char[R];
inverse = new int[R];
for (int i = 0; i < R; i++) // 正反向都初始化为 0 ~ R-1
alphabet[i] = (char)i;
for (int i = 0; i < R; i++)
inverse[i] = i;
} public class01() // 默认构造扩展 aSCII
{
this(256);
} public boolean contains(char c)
{
return inverse[c] != -1;
} public int radix()
{
return R;
} public int lgR() // 表示字母表所需要的二进制位数
{
int lgR = 0;
for (int t = R - 1; t > 0; t <<= 1)
lgR++;
return lgR;
} public int toIndex(char c) // 字符转索引
{
if (c >= inverse.length || inverse[c] == -1)
throw new IllegalArgumentException("\n<toIndex> c >= inverse.length || inverse[c] == -1.\n");
return inverse[c];
} public int[] toIndices(String s) // 字符串转数组
{
char[] source = s.toCharArray();
int[] target = new int[s.length()];
for (int i = 0; i < source.length; i++)
target[i] = toIndex(source[i]);
return target;
} public char toChar(int index)
{
if (index < 0 || index >= R)
throw new IllegalArgumentException("\n<toChar> index < 0 || index >= R.\n");
return alphabet[index];
} public String toChars(int[] indices) // 数组转字符串
{
StringBuilder s = new StringBuilder(indices.length); // 使用 StringBuilder 类,防止平方级时间消耗
for (int i = 0; i < indices.length; i++)
s.append(toChar(indices[i]));
return s.toString();
} public static void main(String[] args)
{
int[] encoded1 = class01.BASE64.toIndices("NowIsTheTimeForAllGoodMen");
String decoded1 = class01.BASE64.toChars(encoded1);
StdOut.println(decoded1); int[] encoded2 = class01.DNA.toIndices("AACGAACGGTTTACCCCG");
String decoded2 = class01.DNA.toChars(encoded2);
StdOut.println(decoded2); int[] encoded3 = class01.DECIMAL.toIndices("01234567890123456789");
String decoded3 = class01.DECIMAL.toChars(encoded3);
StdOut.println(decoded3);
}
}

● 字符串低位优先排序(桶排)

 package package01;

 import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut; public class class01
{
private static final int BITS_PER_BYTE = 8; private class01() { } public static void sort(String[] a, int w) // 每个字符串定长 w 的字符串数组排序
{
int n = a.length;
int R = 256; // 默认基数
String[] aux = new String[n]; for (int d = w - 1; d >= 0; d--) // 从最后一位起,每次循环处理一位
{
int[] count = new int[R + 1];
for (int i = 0; i < n; i++) // 桶计数,这里 count[0] 和 count [1] 暂时为 0
count[a[i].charAt(d) + 1]++;
for (int r = 0; r < R; r++) // 规约前缀和,完成后字母 c 在排序中的起始下标是 count[toIndex[c]],count[0] 固定为 0
count[r + 1] += count[r];
for (int i = 0; i < n; i++) // 向临时数组 aux 写入数据
aux[count[a[i].charAt(d)]++] = a[i];
for (int i = 0; i < n; i++) // 排序完成的数组写回原数组
a[i] = aux[i];
}
} public static void sort(int[] a) // 有符号数组排序,以一个 Byte 为键
{
final int BITS = 32; // int 类型占 256 Bit
final int R = 1 << BITS_PER_BYTE; // 每个 Byte 表示 0 ~ 255
final int MASK = R - 1; // 0xFF,用于只保留最低位的蒙版
final int w = BITS / BITS_PER_BYTE; // int 类型占 4 Byte int n = a.length;
int[] aux = new int[n];
for (int d = 0; d < w; d++)
{
int[] count = new int[R + 1];
for (int i = 0; i < n; i++)
{
int c = (a[i] >> BITS_PER_BYTE * d) & MASK; // 保留从右往左数第 d 个 Byte
count[c + 1]++;
}
for (int r = 0; r < R; r++)
count[r + 1] += count[r];
if (d == w - 1) // 符号位,0x00-0x7F 要排在 0x80-0xFF 的后面
{
int shift1 = count[R] - count[R / 2]; // 低半段(正值)移到后面
int shift2 = count[R / 2];
for (int r = 0; r < R / 2; r++)
count[r] += shift1;
for (int r = R / 2; r < R; r++) // 高半段(负值)移到前面
count[r] -= shift2;
}
for (int i = 0; i < n; i++)
{
int c = (a[i] >> BITS_PER_BYTE * d) & MASK;
aux[count[c]++] = a[i];
}
for (int i = 0; i < n; i++)
a[i] = aux[i];
}
} public static void main(String[] args)
{
String[] a = StdIn.readAllStrings();
int n = a.length; int w = a[0].length(); // 检查字符串是否定长
for (int i = 0; i < n; i++)
assert a[i].length() == w : "\n<main> Strings not fixed length.\n"; sort(a, w); for (int i = 0; i < n; i++)
StdOut.println(a[i]);
}
}

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

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

    ▶ 书中第五章部分程序,包括在加上自己补充的代码,字符串高位优先排序(美国国旗排序) ● 美国国旗排序 package package01; import edu.princeton.cs.algs4 ...

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

    ▶ 书中第五章部分程序,包括在加上自己补充的代码,适用于基因序列的 2-Bit 压缩算法,行程长压缩算法,Huffman 压缩算法,LZW 压缩算法 ● 适用于基因序列的 2-Bit 压缩算法 pac ...

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

    ▶ 书中第五章部分程序,包括在加上自己补充的代码,字符串的二进制表示.十六进制表示.图形表示 ● 二进制表示 package package01; import edu.princeton.cs.al ...

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

    ▶ 书中第五章部分程序,包括在加上自己补充的代码,非确定性有穷自动机(NFA),grep 命令(利用 NFA 匹配) ● 非确定性有穷自动机(NFA) package package01; impor ...

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

    ▶ 书中第五章部分程序,包括在加上自己补充的代码,Knuth-Morris-Pratt 无回溯匹配,Boyer - Moore 无回溯匹配,Rabin - Karp 指纹匹配 ● Knuth-Morr ...

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

    ▶ 书中第五章部分程序,包括在加上自己补充的代码,Trie 树类,Trie 集合,三值搜索树(Ternary Search Trie) ● Trie 树类 package package01; imp ...

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

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

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

    本文由CSDN博客貌似掉线翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...

  9. 《算法》第一章部分程序 part 1

    ▶ 书中第一章部分程序,加上自己补充的代码,包括若干种二分搜索,寻找图上连通分量数的两种算法 ● 代码,二分搜索 package package01; import java.util.Arrays; ...

随机推荐

  1. C#中winform使用相对路径读取文件的方法

    http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece763105392230e54f73b6cd0d3027fa3cf1fd579080101 ...

  2. Hiero中versionscanner模块结构图

    花了两周读这个模块,终于把结构理清楚了,当然新功能也搞定了,搜索条件更宽松,可以找到binitem对象中更多的版本,截图如下: 当然功能也做出来啦: 代码如下: ################### ...

  3. NIO基本操作

    NIO是Java 4里面提供的新的API,目的是用来解决传统IO的问题 NIO主要有三大核心部分:Channel(通道),Buffer(缓冲区), Selector(选择器) Channel(通道) ...

  4. Importing multi-valued field into Solr from mySQL using Solr Data Import Handler

    http://stackoverflow.com/questions/20233837/importing-multi-valued-field-into-solr-from-mysql-using- ...

  5. [转][C#]BarCodeToHTML

    /// <summary> /// 类说明:Assistant /// 编 码 人:苏飞 /// 联系方式:361983679 /// 更新网站:http://www.sufeinet.c ...

  6. 点击input触发弹出框的bug

    先点击第一个input建立弹出框,再点击第二个input打开弹出框,操作点击,同时触发了两个input点击事件.主要原因是建立弹出框时绑定了input1的click事件,再次触发时,又再亿次绑定了in ...

  7. Linux下统计局域网流量

    1:统计10.86.0.0/16网段的内网流量情况 将下面脚本保存成文件traffic-lan.sh(运行后需要等待10秒抓包) tcpdump -nqt src net and dst net ! ...

  8. 利用原生js的Dom操作实现简单的ToDoList的效果

    效果如下: 前端及js代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charse ...

  9. Jmeter(三十六)纵横并发、限制QPS

    一.纵横并发 Jmeter设计并发事件,这应该是一项必备技能. 首先来看并发的概念. 通常在性能测试中会涉及到并发用户数的概念,有关并发用户数(系统用户数)的详解后续再记. (有关并发.并行的概念参考 ...

  10. 为帮助保护你的安全,您的Web浏览器已经限制此文件显示可能访问您的计算机的活动内容

    在开发时,会遇到是要HTML来做UI,是要js与C++进行交互. 在加载完页面后,一些电脑中会出现“为帮助保护你的安全,您的Web浏览器已经限制此文件显示可能访问您的计算机的活动内容”(用IE打开,自 ...