本人现在有两个vector 容器
vector<char> oneword
和 vector<int> fre
前者储存着一个又一个的汉字,每个汉字占一前一后两个char;
后者储存着与之对应的各个汉字出现频率。
所以,fre[i]对应的就是oneword[i*2]和oneword[i*2+1]这两个字符组合起来的汉字的出现频率
现在想根据后面的频率,对汉字进行排序,出现频率越高的放前面。
本人考虑的是,使用现有的快速排序方法,对后面的vector<int>进行快排,然后同时修改函数体,使得排序过程中,int型数据交换的同时,前面对应的两个char型数据也进行交换,这样可以实现,对应的位置的改变。最后本人顺序输出两者,它们还是一一对应的排好序的。
然而这么做了之后,本身正确的统计结果,排序后程序崩溃 =。=
本身,不排序的话,输出的统计结果是正确的。
讨教大家,错误出在哪里?有没有更好更方便的排序方法?
vector<char> oneword
和 vector<int> fre
前者储存着一个又一个的汉字,每个汉字占一前一后两个char;
后者储存着与之对应的各个汉字出现频率。
所以,fre[i]对应的就是oneword[i*2]和oneword[i*2+1]这两个字符组合起来的汉字的出现频率
现在想根据后面的频率,对汉字进行排序,出现频率越高的放前面。
本人考虑的是,使用现有的快速排序方法,对后面的vector<int>进行快排,然后同时修改函数体,使得排序过程中,int型数据交换的同时,前面对应的两个char型数据也进行交换,这样可以实现,对应的位置的改变。最后本人顺序输出两者,它们还是一一对应的排好序的。
然而这么做了之后,本身正确的统计结果,排序后程序崩溃 =。=
本身,不排序的话,输出的统计结果是正确的。
讨教大家,错误出在哪里?有没有更好更方便的排序方法?
#include<fstream> #include<locale> #include<iostream> #include<string> #include<vector> using namespace std; vector<char> oneword;//存放已统计的每个汉字的vector,全局变量 vector<int> fre; //代表每一个汉字的输入频率的vector,全局变量 void quickSort(int s[], int l, int r) { if (l< r) { int i = l, j = r, x = s[l]; char p[2]; p[0] = oneword[l*2]; p[1] = oneword[l*2+1]; while (i < j) { while(i < j && s[j]>= x) // 从右向左找第一个小于x的数 j--; if(i < j) s[i++] = s[j]; oneword[(i-1)*2] = oneword[j*2]; oneword[(i-1)*2+1] = oneword[j*2+1]; while(i < j && s[i]< x) // 从左向右找第一个大于等于x的数 i++; if(i < j) s[j--] = s[i]; oneword[(j+1)*2] = oneword[i*2]; oneword[(j+1)*2+1] = oneword[i*2+1]; } s[i] = x; oneword[i*2] = p[0]; oneword[i*2+1] = p[1]; quickSort(s, l, i - 1); // 递归调用 quickSort(s, i + 1, r); } } int main() { fstream file; string str; //文件内容存到的目标字符串 str unsigned char n[1]; string gstr; //临时变量,用来读入文件 int xx; //xx记录它在oneword数组中的位置 int i,j; //用来计数的变量 file.open("Ci.txt",ios::in|ios::out); do{ str = str + gstr; file>>gstr; } while(!file.eof()); file.close(); //关闭文件 int length = str.length(); //str的总长度 cout<<str<<endl; cout<<length; for(i=0;i<length;i=i+2) { n[0]=str[i]; if(n[0] >= 0xB0 && n[0] <= 0xF7) //是汉字字符 { bool exist; exist = false; for(j=0;j<oneword.size();j=j+2) { if(oneword[j] == str[i] && oneword[j+1] == str[i+1]) {xx = j; exist = true; break; } } if(exist) //已经存在于oneword中 { fre[xx/2]++; //相应 计数 +1 } else //还未存在于oneword之中 { oneword.push_back(str[i]); oneword.push_back(str[i+1]); fre.push_back(1); } } } int *fre1 = new int[fre.size()]; //建立一个名为fre1的int型数组,数据与fre完全相同。为了使用现有函数对fre进行快速排序。 for(i=0;i<fre.size();i++) { fre1[i] = fre[i]; } quickSort(fre1, 0, fre.size()-1); //快速排序函数调用 fstream writefile; writefile.open("result.txt",ios::out); for(i=0;i<oneword.size();i=i+2) //将oneword和fre中的数据一一输出到result.txt之中 { char temp1[3]; temp1[0] = oneword[i]; temp1[1] = oneword[i+1]; temp1[2] = "\0"; writefile<<temp1<<" "; writefile<<fre1[i/2]; writefile<<endl; } writefile.close(); writefile.clear(); return 0; }
解决方案
5
创建一个类管理汉字及其频率,然后直接放在 set 里就行,或 vector 加排序也行。
20
确定用两个字节的话(汉字的话GB 18030可能4字节, UTF8 3~4字节, UTF16 2~4字节),为何不用
#include <vector> #include <algorithm> struct DATA { int i; char c[2]; }; int main() { std::vector<DATA> a = { xxxxxxxxxxxxxx }; std::sort(a.begin(), a.end(), [](const DATA& a, const DATA& b) { return a.i > b.i; }); }
5
处理汉字用wchar_t,wstring,wcout,wfstream
5
本人建议你定义一个类
class ChineseChar
{
public:
char data[2];
//重载 大于,小于,等于操作
}
vector<ChineseChar> list;
这样才是c++的正确用法。
你既用vector,又要将vector转换成数组,你不觉得烦吗?
好好的c++被你当成了c 来用了。
class ChineseChar
{
public:
char data[2];
//重载 大于,小于,等于操作
}
vector<ChineseChar> list;
这样才是c++的正确用法。
你既用vector,又要将vector转换成数组,你不觉得烦吗?
好好的c++被你当成了c 来用了。
5
感觉你的数据结构选的不是很恰当。按照你的描述,每个汉字都是16bit的(2字节),那你直接使用vector<int16_t> oneword来表示汉字,而不要使用oneword[i*2]和oneword[i*2+1]这种结构。之后再统计词频并排序