本来想用字典树的,但字典树是空间换时间的,只有26个字母还好,但文件中还有各种标点符号,觉得空间耗费太大了。。。。就用了还算一般的方法。。
十道海量数据处理:http://blog.csdn.net/v_july_v/article/details/6279498
字典树参考:http://www.cnblogs.com/DiaoCow/archive/2010/04/19/1715337.html && http://blog.csdn.net/bill_ming/article/details/7585009
附代码:见注释(VS2008)
//假设数据能一次全装入内存
#include <iostream>
#include <algorithm>
#include <fstream>
#include <map>
#include <vector>
#include <iterator>
#include <functional>
#include <string>
#include <cstring>
#include <cstdio>
#include <ctime>
#include <cstdlib>
using namespace std;
#define SEARCH_COUNT 10 //打印前多少个单词
//单词类
class WordTop10
{
private :
map<string,int> mapWord; //存储单词
vector<pair<string ,int > > pair_vec; //因为要按map的value排序,借助vector
public :
void insertWord(const string& word); //插入单词到map
void sortWord(); //按map的value排序
void readFile(const string& strFileName); //从文件读数据
void outPut(); //输出
};
//在map中插入一个单词
void WordTop10::insertWord(const string& word)
{
map<string,int>::iterator mit;
mit = mapWord.find(word);
if( mit != mapWord.end())
{
mit->second ++;
}
else
{
mapWord[word] = 1;
}
}
//递减排序
int cmp(const pair<string ,int >& a,const pair<string ,int >& b)
{
return a.second > b.second;
}
//按map中的value排序
void WordTop10::sortWord()
{
for(map<string,int>::iterator map_iter = mapWord.begin(); map_iter != mapWord.end(); ++map_iter)
{
pair_vec.push_back(make_pair(map_iter->first,map_iter->second));
}
sort(pair_vec.begin(),pair_vec.end(),cmp); //排序
}
void WordTop10:: outPut()
{
int i = 0;
for(vector<pair<string ,int > >::iterator cur = pair_vec.begin(); cur != pair_vec.end(); ++cur)
{
i++;
if(i >SEARCH_COUNT) //输出前SEARCH_COUNT个
{
return ;
}
cout << cur->first <<"\t"<<cur->second<<endl;
}
}
//从文件中读取数据
void WordTop10::readFile(const string& strFileName)
{
string text;
// c_str函数的返回值是const char*的,不能直接赋值给char*,所以就需要我们进行相应的操作转化,下面就是这一转化过程。
ifstream in(strFileName.c_str());
if (!in)
{
cout << "~文件打开失败~" << endl;
}
while (in >> text)
{
//text.erase(remove_if(text.begin(),text.end(),bind2nd(equal_to<char>(),'-')), text.end());
//因为读入是以空格分割的,需要处理两边的表标点符号
//取出最后的标点,假设最多有三个尾标点
string::iterator it = text.end();
if(text.length() != 0 && ispunct(text[text.length()-1])) //如果最后那个是标点 /* 注意判断长度啊啊啊啊啊,否则string subscript out of range*/
text.erase(it-1); //去掉最后那个标点
it = text.end();
if(text.length() != 0 && ispunct(text[text.length()-1]))
text.erase(it-1);
it = text.end();
if(text.length() != 0 && ispunct(text[text.length()-1]))
text.erase(it-1);
//有时前面也有符号 ,假设3个
it = text.begin();
if(text.length() != 0 &&ispunct(text[0]))
text.erase(it);
it = text.begin();
if(text.length() != 0 && ispunct(text[0]))
text.erase(it);
it = text.begin();
if(text.length() != 0 &&ispunct(text[0]))
text.erase(it);
//很多字符串带 “--”,特殊处理,--也是标点符号,两头的已在前面处理过,这里处理中间的
size_t npos = text.find("--");
if( npos != -1)
{
string text1 = text.substr(0,npos); //--把text分割成两个单词
string text2 = text.substr(npos+2);
insertWord(text1);
insertWord(text2);
}
else
{
insertWord(text);
}
}
in.close();
in.clear();
return ;
}
//文件属性要是ANSI,而且不能有汉字 。将项目设置中->配置属性->C/C++->语言->默认Char无符号,选择是(/J)即可解决
//参考:http://blog.csdn.net/bill_ming/article/details/8191551
int main()
{
string fileName = "haha.txt";
WordTop10 wordTop;
wordTop.readFile(fileName);
clock_t start = clock();
wordTop.sortWord();
clock_t finish = clock();
double duration = (double)(finish - start) / CLOCKS_PER_SEC;
cout << "排序时间" << duration<<endl;
wordTop.outPut();
return 0;
}