《算法》第五章部分程序 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; ...
随机推荐
- sqlalchemy操作----多表关联
有二张表,一张作者表,一张书表,一个作者写多本书,一本书可以由多个作者写,与是通过新加一张关系表把他们联系起来 #!/usr/bin/env python # -*- coding: utf-8 -* ...
- AM二次开发中选择指定范围内的对象
使用Spatial可以快速选择指定范围内的对象 例如下面的代码可以选择所有在[0,0,0]-[10m,10m,10m]这个盒子之内的对象: 其中ElementsInBox还可以指定对象类型做进一步筛选 ...
- Python 模块EasyGui详细介绍
转载:无知小德 Python 模块EasyGui详细介绍 EasyGui 官网: http://easygui.sourceforge.net 官方的教学文档:http://easygui-docs- ...
- redis(Springboot中封装整合redis,java程序如何操作redis的5种基本数据类型)
平常测试redis操作命令,可能用的是cmd窗口 操作redis,记录一下 java程序操作reids, 操作redis的方法 可以用Jedis ,在springboot 提供了两种 方法操作 Red ...
- HDOJ 2007 平方和与立方和
#include<iostream> #include<algorithm> using namespace std; int main() { int m, n; while ...
- centos7搭建Gitlab服务器
虚拟机配置信息 内存最好大于或等于4G,之前用2G内存搭建,访问出现502报错信息 不考虑selinux和防火墙问题 搭建之前最好关掉selinux和防火墙 临时调增selinux和关闭防火墙 下载G ...
- [UE4]C++中的注释
- SpringMVC 请求响应流程
SpringMVC的工作原理图: SpringMVC流程 1. 用户发送请求至前端控制器DispatcherServlet. 2. DispatcherServlet收到请求调用HandlerMa ...
- PLMN概念和应用设置
PLMN概念和应用设置 1 PLMN概念 PLMN: PLMN(Public Land Mobile Network,公共陆地移动网络) 该网路必须与公众交换电话网(PSTN)互连,形成整个地区或 ...
- IIS Express内存溢出错误
IIS Express只是vs自带的一个简单版开发调试用的web服务器,所以本身貌似并不能容纳太多内存,有时候内存占用超过一定程度就会出错. 这时候可以试着发布到真正的IIS上查看一下,可能就不会出错 ...