文章目录


1 描述

设计和实现一个程序来产生一个置换索引。在一个置换索引中,每一个短语都是这个短语的每一个单词作为索引的。

因此,假如有如下的输入:

The quick brown fox 
jumped over the fence

则输出:

The quick     brown fox 
jumped over the fence
The quick brown fox
jumped over the fence
jumped over the fence
The quick brown fox
jumped over the fence
The quick brown fox

2 思路

每一行的句子中每个单词都会生成一个索引,虽然索引只是一句话中的一个单词,但是还是要将这一句话完整的呈现出来(用空格或者tab键隔开),最后通过字母排序显示。比如The quick brown fox中,会产生四个索引,但是brown按字母排序会排在第一,而在brown后面的就只有fox,所以The quick与brown fox就分开显示。

书中给的算法提示:

  • 1,读入输入的每一行并对每一行输入产生一个轮转的集合。每一个轮转都把输入的下一个单词放在第一个位置上,并把原先的第一个单词旋转到短语的末尾。因此输入的第一行所表示的短语的输出将会是:
The quick brown fox
quick brown fox The
brown fox The quick
fox The quick brown

当然,重要的是要知道最初的短语是在哪里结束,而轮转的开头又是从哪里开始的。

  • 2,对这些轮转集合排序。
  • 3,反向轮转并输出置换索引,其中包含了查找分隔符号、把短语重新连接到一起以及以正确的格式输出短语等操作。

步骤:

  • 一:按行读入字符串,并存储在vector<string>中;
  • 二:对单行进行文本轮转(每次把数组中的第一个单词换成下一个单词,第一个单词变为最后一个单词,也就是实现循环左移)【使用algorithm中的rotate函数,(把迭代器由开始由元素指向下一个元素,实现旋转(类似与一个环一样);返回一个迭代器,它指向原始的第一个元素所在的新位置)】,记录第一个单词的下标以及转换后的字符串;
  • 三:便携字符串转换为小写字母的子程序,然后使用sort按小写字母的字典序进行排序排序;
  • 四:输出,每一行的输出包括两部分:左半部分(从记录的第一单词的位置开始,到数组的最后一个单词结束)和右半部分(从数组的第一个单词开始,到记录的第一个单词结束),输出前先把这两部分的输出存储在数组中,然后比较得到左半部分的最大长度,方便正式输出时补齐空格来实现对齐,最后输出。

3 实现代码

3.1实验结果:

置换索引—————附带完整代码实现_#include

3.2 代码

#include 
#include
#include
#include
#include
#include
#include

using std::cin; using std::endl;
using std::cout; using std::string;
using std::vector; using std::rotate;
using std::setw;

struct Rotation{
vector<string>::size_type first;//第一个单词
vector<string> words;//单行输入
};

//分割字符串
vector<string> split(const string& s){
vector<string> ret;
typedef string::size_type string_size;
string_size i = 0;

while(i != s.size()){
//忽略前段的空白:[先前的i,i)中全部字符都是空格
while(i != s.size() && isspace(s[i])){
i++;
}
//找出下一个单词的终结点
string_size j = i;
//[先前的j,j)中的任意字符都不是空格
while(j != s.size() && !isspace(s[j])){
j++;
}
//找到了一些非空白符
if(i != j){
ret.push_back(s.substr(i, j - i));
i = j;
}
}
return ret;
}

//单行文本轮转
vector<Rotation> rotate_line(const string& line){
vector<Rotation> rotations;
vector<string> words = split(line);//分割成单个单词

//每次都将vector中第一个单词旋转到最后一个
for (vector<Rotation>::size_type i = 0; i != words.size(); ++i) {
Rotation rot = {words.size() - i, words};
rotations.push_back(rot);
//把迭代器由开始由元素指向下一个个元素,实现旋转
// 返回一个迭代器,它指向原始的第一个元素所在的新位置
rotate(words.begin(), words.begin()+1, words.end());
}
return rotations;
}

//多行文本轮转
vector<Rotation> rotate_lines(const vector<string>& lines){
vector<Rotation> rotations;
for (vector<string>::size_type i = 0; i != lines.size(); ++i) {
vector<Rotation> new_rotations = rotate_line(lines[i]);
rotations.insert(rotations.end(), new_rotations.begin(), new_rotations.end());
}
return rotations;
}

//转换为小写字母
string toLowerCase(const string &date){
string str = date;
std::transform(date.begin(), date.end(), str.begin(),::tolower);
//作用是:将某操作应用于指定范围的每个元素
//transform(first,last,result,op);
// first是容器的首迭代器,last为容器的末迭代器,result为存放结果的容器,
// op为要进行操作的一元函数对象或sturct、class;
return str;
}

//整个字符串数组转换为小写字母
vector<string> lowcase(const vector<string>& date){
vector<string> vect;
for (vector<string>::const_iterator it = date.begin(); it != date.end(); ++it) {
vect.push_back(toLowerCase(*it));
}
return vect;
}

//按字母大小排序
bool compare(const Rotation& x, const Rotation& y){
return lowcase(x.words) < lowcase(y.words);
}

void print_rotations(vector<Rotation> rotations){
vector<string> first_halves;
vector<string> second_halves;
string::size_type max_first_halves_width = 0;

for (vector<Rotation>::size_type i = 0; i != rotations.size(); ++i) {
Rotation rot = rotations[i];
string fisrt_half, second_half;

for (vector<string>::size_type j = rot.first; j < rot.words.size(); ++j) {
fisrt_half += rot.words[j] + " ";
}

first_halves.push_back(fisrt_half);

if(fisrt_half.size() > max_first_halves_width) {
max_first_halves_width = fisrt_half.size();
}

for (vector<string>::size_type j = 0; j < rot.first; ++j) {
second_half += rot.words[j] + " ";
}

second_halves.push_back(second_half);

}
for (vector<string>::size_type i = 0; i != first_halves.size(); ++i) {
cout << setw(max_first_halves_width)
<< first_halves[i]
<< "\t"
<< second_halves[i]
<< endl;
}
}

vector<string> read_lines(){
vector<string> lines;
string line;
while(getline(cin, line)){
lines.push_back(line);
}
return lines;
}

int main(int argc,const char *argv[]){
vector<string> lines = read_lines();
vector<Rotation> rotations = rotate_lines(lines);
sort(rotations.begin(), rotations.end(), compare);
print_rotations(rotations);
return 0;
}