《算法》第五章部分程序 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; ...
随机推荐
- 纯css实现
实现此效果 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <!DOCTYPE html><html lang=& ...
- java中的强,软,弱,虚引用
引用的应用场景 我们都知道垃圾回收器会回收符合回收条件的对象的内存,但并不是所有的程序员都知道回收条件取决于指向该对象的引用类型.这正是Java中弱引用和软引用的主要区别. 如果一个对象只有弱引用指向 ...
- Tomcat实战-调优方案
Tomcat的默认配置,性能并不是最优的,可以通过优化tomcat以此来提高网站的并发能力.提高Tomcat的性能可以分为两个方向. 服务器资源 服务器所能提供CPU.内存.硬盘的性能对处理能力有决定 ...
- 【Zabbix3.0】之入门到精通
https://www.cnblogs.com/clsn/p/7885990.html 饿了么技术债 http://server.51cto.com/sOS-555999.htm
- Lucene - CustomScoreQuery 自定义排序
在某些场景需要做自定义排序(非单值字段排序.非文本相关度排序),除了自己重写collect.weight,可以借助CustomScoreQuery. 场景:根据tag字段中标签的数量进行排序(tag字 ...
- PyQt训练BP模型时,显示waiting动图(多线程)
1.实现效果 2.相关代码 实现BP训练模型的线程类 class WorkThread(QtCore.QThread): finish_trigger = QtCore.pyqtSignal() # ...
- uoj#29. 【IOI2014】Holiday
http://uoj.ac/problem/29 经过的点集一定是一个包含start的区间,为了经过这个区间内所有点,必须先到达一个区间端点,再到达另一个区间端点,剩余的步数则贪心选区间内最大价值的点 ...
- SQLServer为已有数据的表添加一个自增列
如果我们从Excel中导入到SQL中大量数据时,如果需要再单独处理特别需要一个字段去表示处理到那条数据了,这时因为没有主键就可以使用以下方式为每条数据添加id ,) not null
- Spring-framework应用程序启动loadtime源码分析笔记(二)——@Transactional
@Transactional标识类或方法,使方法被执行时使用事务方式执行,这里只讨论PROXY方法增强方法.使用@EnableTransactionManagement,默认model=AdviceM ...
- chrome 抓包的小功能--preserve log (记录页面跳转后,所有的抓包记录)
1.记录页面跳转后,所有的抓包记录,勾上