字符串(1)——字符串排序
来源:互联网 发布:dbx260软件中文版 编辑:程序博客网 时间:2024/05/21 15:49
字符串排序
无数的重要领域都是基于字符串处理的。本章将会学习一些经典的字符串处理算法。
我们将学习两类不同的字符串排序算法。
1)从右到左检查键中的字符。这种方法一般被称为低位优先,适用于键的长度都相同的字符串排序。
2)从左到右检查键中的字符,这种方法一般被称为高位优先,和快排类似,通过递归来快速切分。
键索引计数法
做为两种排序方法的基础,我们需要用到键索引计数法。
他的作用是通过键的出现频率构造索引,然后用过索引排序数组。
具体分为四部:
1)频率统计:count数组计算每个键出现的频率,存储到count[r+1]
2)将频率转换为索引:从前往后count[r+1]都加上count[r],构造出索引的位置
3)数据分类:将元素复制到辅助数组aux[]中进行排序
4)回写:将排序后的元素复制回原数组
代码:
int N = a.size();vector<string> aux(N);vector<int> count(R + 1,0);for (int i = 0; i < N; i++)//计算出现频率count[a[i].key() + 1]++;for (int r = 0; r < R; r++)//将频率转换为索引count[r + 1] += count[r];for (int i = 0; i < N; i++)//将元素分类aux[count[a[i].key()]++] = a[i];for (int i = 0; i < N; i++)//回写a[i] = aux[i];
低位优先的字符串排序
低位优先的字符串排序算法能够稳定地将定长字符串排序。
缺点就是字符串长度必须是固定的。
具体步骤就是,从右往左对字符串的每一个字符进行键索引计数法排序。
代码:
#ifndef LSD_H#define LSD_H#include<string>using std::string;#include<vector>using std::vector;class LSD{public:void sort(vector<string> &a, int w)//w为字符串长度{int N = a.size();int R = 256;//字符的数量vector<string> aux(N);for (int d = w - 1; d >= 0; d--){vector<int> count(R + 1,0);for (int i = 0; i < N; i++)//计算出现频率count[a[i].at(d) + 1]++;for (int r = 0; r < R; r++)//将频率转换为索引count[r + 1] += count[r];for (int i = 0; i < N; i++)//将元素分类aux[count[a[i].at(d)]++] = a[i];for (int i = 0; i < N; i++)//回写a[i] = aux[i];}}};#endif
测试用例:
#include<iostream>#include<fstream>#include"LSD.h"using namespace std;int main(){vector<string> a;string aa;while (cin >> aa)a.push_back(aa);LSD s;s.sort(a,a[0].size());for (auto w : a)cout << w << endl;system("pause");return 0;}
高位优先的字符串排序
要实现一个通用字符串排序算法(字符串长度不一定相等),我们应该考虑从左向右遍历所有的字符。这种思想的一个很自然的方法就是一种递归算法,即高位优先的字符串排序。
具体方法是:将字符串从左往右开始对字符进行键索引计数法排序,然后递归对每个索引频率内的数据单独进行下一位字符排序。(类似于快排)
因为字符串长度是不同的,所以我们应该注意在计算频率时将长度小于所查字符的单独放一栏。所以我们需要对at()函数进行重构,当没有所查字符时返回-1,而键索引计数法也需要将查找的位置后移一位。
代码:
#ifndef MSD_H#define MSD_H#include<string>using std::string;#include<vector>using std::vector;class MSD{private:int R = 256;//基数int M = 15;//小数组的切换阙值vector<string> aux;int at(string s, int d){ if (d < s.size())return s.at(d); else return -1; }public:void sort(vector<string> &a){int N = a.size();aux=vector<string>(N);sort(a, 0, N - 1, 0);}void sort(vector<string> &a, int lo, int hi, int d){//以d个字符为键将a[lo]至a[hi]排序if (hi <= lo)return;//if(hi<=lo+M){insertsort(a,lo,hi,d);return;}vector<int> count(R + 2);for (int i = lo; i <= hi; i++)//计算频率count[at(a[i], d) + 2]++;for (int r = 0; r < R + 1; r++)//将频率转换为索引count[r + 1] += count[r];for (int i = lo; i <= hi; i++)//数据分类aux[count[at(a[i], d) + 1]++] = a[i];for (int i = lo; i <= hi; i++)//回写a[i] = aux[i - lo];//递归的以每个字符为键进行排序for (int r = 0; r < R; r++)sort(a, lo + count[r], lo + count[r + 1] - 1, d + 1);}};#endif
测试用例:
#include<iostream>#include<fstream>#include"MSD.h"using namespace std;int main(){vector<string> a;string aa;while (cin >> aa)a.push_back(aa);MSD s;s.sort(a);for (auto w : a)cout << w << endl;system("pause");return 0;}
三向字符串快速排序
与三向快排相类似,将字符串以首字符进行三切分快排,然后递归对切分出来的同类子集进行次一字符的快排,直到元素字符排空为止。
代码:
#ifndef QUICK3STRING_H#define QUICK3STRING_H#include<string>using std::string;#include<vector>using std::vector;class Quick3string{private:int at(string s, int d){if (d < s.size())return s.at(d);else return -1; }void eaxh(vector<string> &a, int i,int j){string t = a[i];a[i] = a[j];a[j] = t;}public:void sort(vector<string> &a){ sort(a, 0, a.size() - 1, 0); }void sort(vector<string> &a, int lo, int hi, int d){if (hi <= lo)return;int lt = lo, gt = hi;//左切分指针和右切分指针int v = at(a[lo], d);//提取切分的字符int i = lo + 1;//遍历指针while (i <= gt){int t = at(a[i], d);//查看的字符if (t < v)eaxh(a, lt++, i++);else if (t > v)eaxh(a, i, gt--);else i++;}sort(a, lo, lt - 1, d);if (v >= 0)sort(a, lt, gt, d + 1);sort(a, gt + 1, hi, d);}};#endif
测试用例:
#include<iostream>#include<fstream>#include"Quick3string.h"using namespace std;int main(){vector<string> a;string aa;while (cin >> aa)a.push_back(aa);Quick3string s;s.sort(a);for (auto w : a)cout << w << endl;system("pause");return 0;}
算法性能对比
阅读全文
0 0
- 字符串(1)——字符串排序
- 华为OJ—字符串排序
- 华为OJ平台试题 ——字符串:字符串比较排序
- 指针(字符串排序)
- hdu3293(字符串排序)
- 字符串版(排序)
- 字符串排序(指针)
- 字符串:字符串排序
- 字符串系列——词典排序
- 经典题目——字符串全排序
- Android进阶——字符串排序
- 华为机试——字符串排序
- 华为OJ——字符串排序
- Problem L: STL——字符串排序
- Problem L: STL——字符串排序
- Problem : STL——字符串排序
- NOJ第56——字符串排序
- 华为OJ——字符串排序
- 二级C语言上机模拟题及答案[1]_等级考试模拟题
- 05年9月等级考试二级C语言考前上机密卷_计算机等级真题
- 继承
- 计算机等级考试上机模拟题(二级C语言)_等级考试模拟题,计算机等级考试,计算机考试
- hdu1548
- 字符串(1)——字符串排序
- Linux I/O模型
- 三级数据库技术笔试样题_等级考试模拟题
- 三级PC技术笔试样题_等级考试模拟题
- php全等于
- 2004年9月全国计算机等级考试二级C笔试试题_计算机等级真题
- 计算机试题
- 清华大学计算机编译原理及操作系统试题
- 计算机等级考试三级笔试试卷网络技术试题【附答案】