有一个关于Vector的问题

C++语言 码拜 8年前 (2016-09-20) 1379次浏览
本人现在有两个vector 容器
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 来用了。

5

感觉你的数据结构选的不是很恰当。按照你的描述,每个汉字都是16bit的(2字节),那你直接使用vector<int16_t> oneword来表示汉字,而不要使用oneword[i*2]和oneword[i*2+1]这种结构。之后再统计词频并排序

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明有一个关于Vector的问题
喜欢 (0)
[1034331897@qq.com]
分享 (0)