本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循 署名-非商业用途-保持一致 的创作共用协议.
对于字符串数据排序问题的总结, 如有错误, 欢迎指出.
键索引计数法
这种排序算法是以下两种排序算法的基础
假设有以下一组数据
组号 | 姓名 |
---|---|
2 | Anderson |
3 | Brown |
3 | Davis |
1 | Harris |
算法步骤:
- 首先进行组号出现的频率统计, 使用count数组记录每个组号出现的次数
- 将频率转换为索引, 使用count来计算每个组号在排序结果中的起始索引位置
- 数据分类, 将count[]转换为索引表后, 将名字移动到对应的辅助数组中排序
- 回写, 将aux数组的数据回写到原排序数组中
低位优先的字符串排序
低位优先排序算法是通过建索引计数法完成的, 从每个字符串的最右侧开始, 以每个位置的字符作为key键(相当于组号), 用 键索引计数法
对字符串排序W遍(假设所有字符串长度为W)
由于键索引计数法的排序是稳定的, 则可以推出低位优先的字符串排序算法能够稳定的排序定长字符串
算法缺点:
- 只能用于处于等长字符串排序
- 需要额外的count[]和aux[]数组空间
高位优先的字符串排序
高位优先排序算法用于更通用的情形(字符串不定长), 首先用 键索引计数法
对所有字符串首字母排序, 然后在 递归的
将每个首字母所对应的子数组排序(忽略首字母)
当指定位置超出字符串的末尾应该返回 -1
. 越界则输出-1. 这种转换意味着字符串中的每个字符都可能产生R+1中不同的值,同时键索引计数法本来就需要一个额外的位置,所以使用代码int count[] = new int[R + 2];
在高位优先排序中, 每次递归过程都会创建一个count数组并转换成索引, 当数据量过大, 会造成很大的 空间代价
, 所以当进行小数组排序时, 切换为使用 插入排序算法
, 避免重复检查已知相同字符带来的成本
算法缺点:
- 高位优先的字符串排序使用了两个辅助数组(aux[]和count[])
- 高位优先的字符串排序的最坏情况就是所有的键均相同
三向字符串快速排序
根据高位优先, 改进为快速排序策略, 这种方法是前两种方法的结合
根据字符串数组的首字母进行三向切分, 然后 递归的
将得到的三个子数组排序, 一个含有所有首字母小于切分字符的字符串子数组, 一个含有所有首字母等于切分字符的子数组, 一个含有所有首字母大于气氛字符串的子数组
三项字符串快速排序能够很好地处理等值键、有较长公共前缀的键、取值范围较小的键和小数组,且只需要递归所需的隐式栈的额外空间
参考链接
-
<算法>
-
普林斯顿-Algorithm II