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

来源:互联网 发布:蓝牙共享网络给电脑 编辑:程序博客网 时间:2024/05/22 10:35

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
1 0