《算法》第五章部分程序 part 3
▶ 书中第五章部分程序,包括在加上自己补充的代码,字符串高位优先排序(美国国旗排序)
● 美国国旗排序
package package01; import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.Stack; public class class01
{
private static final int BITS_PER_BYTE = 8;
private static final int BITS_PER_INT = 32;
private static final int R = 256;
private static final int CUTOFF = 15; private class01() {} public static void sort(String[] a)
{
sortKernel(a, 0, a.length - 1);
} public static void sortKernel(String[] a, int lo, int hi)
{
Stack<Integer> st = new Stack<Integer>();
int[] first = new int[R + 2], next = new int[R + 2];
int d = 0;
for (st.push(lo), st.push(hi), st.push(d); !st.isEmpty();)
{
d = st.pop(); hi = st.pop(); lo = st.pop();
if (hi <= lo + CUTOFF)
{
insertion(a, lo, hi, d);
continue;
}
for (int i = lo; i <= hi; i++) // 以字符串的第 d 位进行统计
first[charAt(a[i], d) + 2]++;
first[0] = lo; // 前部垫起
for (int c = 0; c <= R; c++) // 前缀和与子问题分配
{
first[c + 1] += first[c];
if (c > 0 && first[c + 1] - 1 > first[c]) // 存在至少 2 个第 d 位为 c 的字符串,注意排除 c == 0 的情况
{
st.push(first[c]); // 添加子问题,对第 d 位为 c 的所有字符串关于第 d+1 位进行排序
st.push(first[c + 1] - 1);
st.push(d + 1);
}
}
for (int c = 0; c < R + 2; c++) // 拷贝 first 到 next 中,next 用于搬运字符串过程中的变化索引
next[c] = first[c];
for (int k = lo; k <= hi; k++) // 搬运字符串到指定位置,循环将 a[k] 作为交换的临时位置
{
int c = charAt(a[k], d) + 1; // 取 a[k] 的第 d 位的下一个字符
for (; first[c] > k; c = charAt(a[k], d) + 1) // 只要 c 出现的位置排在 k 后面,就交换 a[k] 和 a[next[c]],并且 next[c]向后移一个位置
exch(a, k, next[c]++);
next[c]++; // 全部移完了,next[c] 再自增 1,表示 c 开头的索引已经等于 first[c+1],避免重复排序
}
for (int c = 0; c < R + 2; c++) // 清除 first 和 next
first[c] = next[c] = 0;
}
} private static void insertion(String[] a, int lo, int hi, int d)
{
for (int i = lo; i <= hi; i++)
{
for (int j = i; j > lo && less(a[j], a[j - 1], d); j--)
exch(a, j, j - 1);
}
} private static int charAt(String s, int d)
{
assert d >= 0 && d <= s.length();
if (d == s.length())
return -1;
return s.charAt(d);
} private static void exch(String[] a, int i, int j)
{
String temp = a[i];
a[i] = a[j];
a[j] = temp;
} private static boolean less(String v, String w, int d)
{
assert v.substring(0, d).equals(w.substring(0, d));
for (int i = d; i < Math.min(v.length(), w.length()); i++)
{
if (v.charAt(i) == w.charAt(i))
continue;
return v.charAt(i) < w.charAt(i);
}
return v.length() < w.length();
} public static void sort(int[] a) // 数组排序
{
sortKernel(a, 0, a.length - 1);
} private static void sortKernel(int[] a, int lo, int hi)
{
Stack<Integer> st = new Stack<Integer>();
int[] first = new int[R + 1], next = new int[R + 1];
int mask = R - 1, d = 0;
for (st.push(lo), st.push(hi), st.push(d); !st.isEmpty();)
{
d = st.pop(); hi = st.pop(); lo = st.pop();
if (hi <= lo + CUTOFF)
{
insertion(a, lo, hi, d);
continue;
}
int shift = BITS_PER_INT - BITS_PER_BYTE * (d + 1); // 取从左往右的第 d 字节
for (int i = lo; i <= hi; i++)
first[((a[i] >> shift) & mask) + 1]++;
first[0] = lo;
for (int c = 0; c < R; c++)
{
first[c + 1] += first[c];
if (d < 3 && first[c + 1] - 1 > first[c]) // c > 0 条件改为,当前字节不是最低字节
{
st.push(first[c]);
st.push(first[c + 1] - 1);
st.push(d + 1);
}
}
for (int c = 0; c < R + 1; c++)
next[c] = first[c];
for (int k = lo; k <= hi; k++)
{
int c = (a[k] >> shift) & mask;
for (; first[c] > k; c = (a[k] >> shift) & mask)
exch(a, k, next[c]++);
next[c]++;
}
for (int c = 0; c < R + 1; c++)
first[c] = next[c] = 0;
}
} private static void insertion(int[] a, int lo, int hi, int d)
{
for (int i = lo; i <= hi; i++)
{
for (int j = i; j > lo && less(a[j], a[j - 1], d); j--)
exch(a, j, j - 1);
}
} private static void exch(int[] a, int i, int j)
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
} private static boolean less(int v, int w, int d)
{
int mask = R - 1;
for (int i = d; i < 4; i++)
{
int shift = BITS_PER_INT - BITS_PER_BYTE * (i + 1);
int a = (v >> shift) & mask, b = (w >> shift) & mask;
if (a == b)
continue;
return a < b;
}
return false;
} public static void main(String[] args)
{
if (args.length > 0 && args[0].equals("int"))
{
int[] a = StdIn.readAllInts();
sort(a); for (int i = 0; i < a.length; i++)
StdOut.println(a[i]);
}
else
{
String[] a = StdIn.readAllStrings();
sort(a); for (int i = 0; i < a.length; i++)
StdOut.println(a[i]);
}
}
}
● 美国国旗排序 2
package package01; import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.Stack; public class class01
{
private static final int R = 256;
private static final int CUTOFF = 15; private class01() {} public static void sort(String[] a)
{
sortKernel(a, 0, a.length - 1);
} public static void sortKernel(String[] a, int lo, int hi)
{
Stack<Integer> st = new Stack<Integer>();
int[] count = new int[R + 1];
int d = 0;
for (st.push(lo), st.push(hi), st.push(d); !st.isEmpty();)
{
d = st.pop(); hi = st.pop(); lo = st.pop();
if (hi <= lo + CUTOFF)
{
insertion(a, lo, hi, d);
continue;
}
for (int i = lo; i <= hi; i++)
count[charAt(a[i], d) + 1]++;
count[0] += lo;
for (int c = 0; c < R; c++)
{
count[c + 1] += count[c]; // count[c] 表示键值不大于 c 的元素个数(相当于字符 c+1 起始位置先前 1 格)
if (c > 0 && count[c + 1] - 1 > count[c])
{
st.push(count[c]);
st.push(count[c + 1] - 1);
st.push(d + 1);
}
}
for (int r = hi; r >= lo; r--) // r 从后向前
{
int c = charAt(a[r], d) + 1;
for (; r >= lo && count[c] - 1 <= r;)
{
if (count[c] - 1 == r)
count[c]--;
r--;
if (r >= lo)
c = charAt(a[r], d) + 1;
}
if (r < lo) // r 已经降到 lo 以下,调整完成
break;
for (count[c]--; count[c] != r; c = charAt(a[r], d) + 1, count[c]--)
exch(a, r, count[c]);
}
}
for (int c = 0; c < R + 1; c++) // 清除 count
count[c] = 0;
} private static void insertion(String[] a, int lo, int hi, int d)
{
for (int i = lo; i <= hi; i++)
{
for (int j = i; j > lo && less(a[j], a[j - 1], d); j--)
exch(a, j, j - 1);
}
} private static int charAt(String s, int d)
{
assert d >= 0 && d <= s.length();
if (d == s.length())
return -1;
return s.charAt(d);
} private static void exch(String[] a, int i, int j)
{
String temp = a[i];
a[i] = a[j];
a[j] = temp;
} private static boolean less(String v, String w, int d)
{
assert v.substring(0, d).equals(w.substring(0, d));
for (int i = d; i < Math.min(v.length(), w.length()); i++)
{
if (v.charAt(i) == w.charAt(i))
continue;
return v.charAt(i) < w.charAt(i);
}
return v.length() < w.length();
} public static void main(String[] args)
{
String[] a = StdIn.readAllStrings();
sort(a); for (int i = 0; i < a.length; i++)
StdOut.println(a[i]);
}
}
《算法》第五章部分程序 part 3的更多相关文章
- 《算法》第五章部分程序 part 8
▶ 书中第五章部分程序,包括在加上自己补充的代码,适用于基因序列的 2-Bit 压缩算法,行程长压缩算法,Huffman 压缩算法,LZW 压缩算法 ● 适用于基因序列的 2-Bit 压缩算法 pac ...
- 《算法》第五章部分程序 part 7
▶ 书中第五章部分程序,包括在加上自己补充的代码,字符串的二进制表示.十六进制表示.图形表示 ● 二进制表示 package package01; import edu.princeton.cs.al ...
- 《算法》第五章部分程序 part 6
▶ 书中第五章部分程序,包括在加上自己补充的代码,非确定性有穷自动机(NFA),grep 命令(利用 NFA 匹配) ● 非确定性有穷自动机(NFA) package package01; impor ...
- 《算法》第五章部分程序 part 5
▶ 书中第五章部分程序,包括在加上自己补充的代码,Knuth-Morris-Pratt 无回溯匹配,Boyer - Moore 无回溯匹配,Rabin - Karp 指纹匹配 ● Knuth-Morr ...
- 《算法》第五章部分程序 part 4
▶ 书中第五章部分程序,包括在加上自己补充的代码,Trie 树类,Trie 集合,三值搜索树(Ternary Search Trie) ● Trie 树类 package package01; imp ...
- 《算法》第五章部分程序 part 2
▶ 书中第五章部分程序,包括在加上自己补充的代码,字符串高位优先排序(计数 + 插排),(原地排序),(三路快排,与前面的三路归并排序相同) ● 计数 + 插排 package package01; ...
- 《算法》第五章部分程序 part 1
▶ 书中第五章部分程序,包括在加上自己补充的代码,字母表类,字符串低位优先排序(桶排) ● 字母表类 package package01; import edu.princeton.cs.algs4. ...
- Gradle 1.12用户指南翻译——第四十五章. 应用程序插件
本文由CSDN博客貌似掉线翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Githu ...
- 《算法》第一章部分程序 part 1
▶ 书中第一章部分程序,加上自己补充的代码,包括若干种二分搜索,寻找图上连通分量数的两种算法 ● 代码,二分搜索 package package01; import java.util.Arrays; ...
随机推荐
- OpenGL学习记录
1.QT OpenGL工程建立: http://www.cnblogs.com/tornadomeet/archive/2012/08/22/2651574.html 2.Qt自定义界面类并提升(提升 ...
- Java8新特性值Lambda --->匿名函数
Lambda:表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名 ...
- Spring-framework应用程序启动loadtime源码分析笔记(二)——@Transactional
@Transactional标识类或方法,使方法被执行时使用事务方式执行,这里只讨论PROXY方法增强方法.使用@EnableTransactionManagement,默认model=AdviceM ...
- java1.8新特性(四 创建 stream对象)
java1.8 提供了 stream对象 可以用作 对 集合 数组的 一系列操作,都是基于lambda 表达式 ,所以得先熟悉lambda 表达式 集合创建stream对象 // 1.集合创建stre ...
- Java-Runoob-高级教程-实例-数组:13. Java 实例 – 数组交集
ylbtech-Java-Runoob-高级教程-实例-数组:13. Java 实例 – 数组交集 1.返回顶部 1. Java 实例 - 数组交集 Java 实例 以下实例演示了如何使用 reta ...
- Java zxing生成二维码所需的jar包
免费的,不需要积分. 共有2个jar包, 链接: https://pan.baidu.com/s/1QJcEkRQOp1NdrNAgGC6LvQ 密码: 4524
- [UE4]UI动画
- Socket的长连接和短连接
讨论Socket必讨论长连接和短连接 一.长连接和短连接的概念 1.长连接与短连接的概念:前者是整个通讯过程,客户端和服务端只用一个Socket对象,长期保持Socket的连接:后者是每次请求,都新建 ...
- C# 连接数据库实现增删改查
class Program { private static string urls = "server=127.0.0.1;port=3306;user=root;password=123 ...
- python类型强转&二级容器
Number 类型强转 int : ---->>> float, bool, complex, str Float : ---->> ...