您的位置:首页 > 其它

统计单词出现个数(STL-map求解)

2017-02-16 22:53 387 查看
string strs[] = { “zhangsan”, “zhangsan”, “lisi”, “wangwu”, “lisi”, “zhaoliu”,”lisi” };

问题一:统计单词出现的次数

看到这个题,有很多思路可以解决,目前刚好在了解STLset/map中,所以就用map来解这个问题。

根据map的诸多借口可以有多种方法来解决这个问题,但是其实都是运用的map的特性。

觉得下面这些有必要了解一下:

首先map是关联容器,之前set篇说过。map的元素都通过元素键值自动排序,拥有并且独一无二的键值,因为map不允许两个元素拥有相同的键值。map的元素都是pair类型。同时拥有键值(key)和实值(value)。pair的第一个元素是键值,第二个元素是实值。另外map的底层是由RB-tree为底层机制,因此map对插入,删除,查找能保证log(N)的时间复杂度。对于海量的数据的插入和查询,map是一个不错的选择。

map形式如下:

template < class Key,                                    // map::key_type
class T,                                       // map::mapped_type
class Compare = less<Key>,
// map::key_compare 这里可以看到缺省采用的是递增排序(升序)
class Alloc = allocator<pair<const Key,T> >    // map::allocator_type
> class map;


map::insert()形式如下:



而pair的定义如下:

template<class TI,class T2>
struct pair
{
typedef TI first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair():first_type(T1()),second_type(T2()){}
pair(const T1& a,const T2& b):first(a),second(b){}
}


可以将单词当作键值,次数当作实值

方法一:插入单词前先就行判断,是否已经拥有,如果已经插入则直接给实值+1,如果没有则进行插入操作。

string strs[] = { "zhangsan", "zhangsan", "lisi", "wangwu", "lisi", "zhaoliu","lisi" };
map<string, int> CountMap;
for (size_t idx = 0; idx < sizeof(strs) / sizeof(strs[0]); ++idx)
{
//第一种
map<string, int>::iterator it = CountMap.find(strs[idx]);
if (it != CountMap.end())
{
it->second++;
}
else
{
CountMap.insert(pair<string, int>(strs[idx], 1));
}
}


方法二:要知道如定义一个pair类型的第二个元素会返回一个false),则说明map中已经存在这个单词,给实值+1就可以


string strs[] = { "zhangsan", "zhangsan", "lisi", "wangwu", "lisi", "zhaoliu","lisi" };
map<string, int> CountMap;
pair<map<string, int>::iterator, bool> ret;
for (size_t idx = 0; idx < sizeof(strs) / sizeof(strs[0]); ++idx)
{
//第二种
ret = CountMap.insert(pair<string, int>(strs[idx], 1));
if (ret.second == false)
{
ret.first->second++;
}
}


方法三:需要对map了解,直接使用库里提供的[]运算符重载。通过键值找节点,直接给给实值+1.


string strs[] = { "zhangsan", "zhangsan", "lisi", "wangwu", "lisi", "zhaoliu","lisi" };
map<string, int> CountMap;
for (size_t idx = 0; idx < sizeof(strs) / sizeof(strs[0]); ++idx)
{
CountMap[strs[idx]]++;
}




可以看到单词的个数已经统计出来。第三种方法就充分说明熟悉STL库的作用,想想这要是在笔试别人不需要多想直接就能得到答案,而我们还在思考应该怎么求(这也许就是差距啊)

问题二: 找出出现次数最多的三个单词

首先想的是将所有单词都插入到vector中,然后在用sort进行排序,但是仔细想想一个string类型就占很多字节,如果单词稍微多点的话,岂不是太浪费空间了?

我们可以打破惯性思维,为什么非得把单词存到vector中,为什么不把单词所在节点的迭代器放到vector中呢?然后再通过自定义比较类型比较次数从而使用sort就行排序。

vector<map<string, int>::iterator> v;
map<string, int>::iterator CountIt = CountMap.begin();
while (CountIt != CountMap.end())
{
v.push_back(CountIt);
++CountIt;
}
struct Compare
{
bool operator()(map<string, int>::iterator l, map<string, int>::iterator r)
{
return l->second > r->second;
}
};
sort(v.begin(),v.end(),Compare());


测试:



完整代码入下:

#define _CRT_SECURE_NO_WARNINGS

#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
#include<set>
#include<queue>
using namespace std;
int main()
{
string strs[] = { "zhangsan", "zhangsan", "lisi", "wangwu", "lisi", "zhaoliu","lisi" };
map<string, int> CountMap;
pair<map<string, int>::iterator, bool> ret;
for (size_t idx = 0; idx < sizeof(strs) / sizeof(strs[0]); ++idx)
{
//第一种
/*map<string, int>::iterator it = CountMap.find(strs[idx]);
if (it != CountMap.end())
{
it->second++;
}
else
{
CountMap.insert(pair<string, int>(strs[idx], 1));
} */

//第二种
/*ret = CountMap.insert(pair<string, int>(strs[idx], 1));
if (ret.second == false)
{
ret.first->second++;
}*/
//第三种
CountMap[strs[idx]]++;
/*
//operator[]定义:
mapped_type& operator[](const key_type& _Keyval)
{ // find element matching _Keyval or insert with default mapped
iterator _Where = this->lower_bound(_Keyval);
if (_Where == this->end()
|| this->_Getcomp()(_Keyval, this->_Key(_Where._Mynode())))

_Where = this->emplace_hint(_Where,
piecewise_construct,
_STD forward_as_tuple(_Keyval),
tuple<>());

return (_Where->second);
}*/
}
//用sort排序

vector<map<string, int>::iterator> v; map<string, int>::iterator CountIt = CountMap.begin(); while (CountIt != CountMap.end()) { v.push_back(CountIt); ++CountIt; } struct Compare { bool operator()(map<string, int>::iterator l, map<string, int>::iterator r) { return l->second > r->second; } }; sort(v.begin(),v.end(),Compare());map<string, int>::iterator it = CountMap.begin();
system("pause");
return 0;
}


进击的Mis_tian
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: