取map容器的前10大(根据每一个value排序)元素

来源:互联网 发布:js处理json字符串 编辑:程序博客网 时间:2024/06/04 19:06

 XX公司的笔试题:

  给定一个仅包含英文字母和空格的字符串,请实现一个函数找出该字符串中出现次数最多的10个字母(不区分大小写)。

      当时的解答是:

#include <iostream>
#include <algorithm>
#include <map>

#include <vector>
using namespace std;

bool compare_map(const pair<char, int> &p1, const pair<char,int> &p2)
{
     return p1.second < p2.second;
}
char* Find_top10Char(const char* str)
{
     if (!str)
         return NULL;
     const char *pStr = str;
     static char res[11] ;

     memset(res, 0, sizeof(res));
     map<char,int> tmp;
     while (*pStr != '/0')
     {
          char tp = *pStr;

          if(*pStr == ' ')

               pStr++,continue;
          if (*pStr + 32 < 122)  //如果是大写,转换成小写
          {
                tp = *pStr + 32;
          }
          tmp[tp]++;
          pStr++;
 }
 map<char,int>::iterator iter = tmp.end(); 
 for (int i = 0; i < 10 && !tmp.empty(); ++i)
 {
      iter = max_element(tmp.begin(), tmp.end(), compare_map);  //效率太低
      if (iter != tmp.end())
      {
          res[i] = iter->first;
          tmp.erase(iter);
          continue;  
      } 
      break;
  } 
      return res;
}

//test
int main()
{
     const char *pp = "aaajjjj jaaaaf fffjjjllllf fflllo ffoaoaaoottotrrttrwrwqwqu";
     char *res = Find_top10Char(pp);
     cout<<res<<endl;
     return 1;
}

  将源字符串中出现过的字符都记录下来,放在map容器的pair中,字符每出现多一次就将该pair的second加1。知道遍历完整个字符串。

  接下来,需要对map容器根据pair的second进行排序,得到前10个元素。可是map容器本身就是已排好序的容器(根据每一个key),因此不能改变该容器的顺序,只能另谋它法了。

  要想得到和map结构一样的非排序容器,可以用vector或list来完成,将pair<char,int>作为它的元素,取出该容器前10大的元素,可用partial_sort()这一函数。

      在此采用vector来实现:

vector<pair<char,int> > vec(tmp.size());   //先预留空间,避免频繁更换内存块

//copy(tmp.begin(), tmp.end(), back_inserter(vec));

int idx = 0;  //在下面定义map迭代器处接着定义idx,老是编译错误,不知为啥

for (map<char, int>::iterator iter = tmp.begin(); iter != tmp.end(); ++iter, ++idx)
{
   vec[idx] = make_pair(iter->first, iter->second);

}
partial_sort(vec.begin(), vec.begin() + 9, vec.end(), compare_map);  //此时应将compare_map函数"改>"

然后再:

for (int i = 0; i < 10 && !vec.empty(); ++i)
{
    pair<char,int> &pr = vec.front();
    res[i] = pr.first;
    vec.erase(vec.begin());
}

 

这里有几个疑问:

1.为什么改用partial_sort之后,效率就高了呢?它的原理是什么?

2.为什么要用vector而不用list呢?假如需要存放的数据很多的话,vector不是低效吗?

3.为什么构造vec对象的时候不采用vector<pair<char,int> > vec(tmp.begin(), tmp.end());直接往vec填元素呢?

答:

1.partial_sort是通过堆排序实现的,具体看“从partial_sort挖掘堆排序”这篇。

2.正是考虑到vector是顺序存储元素的,所以预先分配了足够的空间,然后通过下标即可对其每个元素赋值。

3.这样的用法本身有问题,在模板类vector中的iterator只是一个unsigned int类型,而map或list等模板类中的iterator却是class,当然不能通过编译,起码VC6不行。

原创粉丝点击