求一个数组中出现次数前k种的元素

本文介绍使用C++标准库中的map数据结构统计水果出现次数的方法,包括两种遍历方式及其优劣对比。此外,还探讨了如何找出出现频率最高的前K个元素,提供了基于排序和堆的不同实现思路。
map<string, int> fruitCount;//创建map对象  
for (int i = 0; i < sizeof(fruits) / sizeof(fruits[0]); ++i)  
{  
    map<string, int>::iterator it = fruitCount.find(fruits[i]);//创建map迭代器  
    if (it != fruitCount.end())//先查找看该字符数组内是否存在该字符串  
    {  
        it->second++;//给该类对象的计数+1   
    }  
    else  
    {  
        fruitCount.insert(pair<string, int>(fruits[i], 1));  
    }  
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

缺点:如果map中没有要插入的这个水果,则需要遍历两次map。

思路二:只遍历一次map 
insert的返回值pair。既然不管是否插入成功,它都能返回我们需要的这个元素的迭代器。那么,我们可以先插入,然后对其返回值进行保存,如果该返回值得第二个参数是true,表示插入成功,不进行其他操作,如果为flase,表示插入失败,那么其返回的第一个参数将会带回已经存在的这个被插入元素的迭代器,当然轻而易举就可以通过迭代器拿到这个元素的第二个参数V。

void CalculateFruitCount(map<string,int>& m, string fruits[], size_t size)  
{  
    for (size_t i = 0; i < size; i++)  
    {  
        //m[fruits[i]]++;    //map中有operator[]的重载,其内容等同于下边代码  

        pair<map<string, int>::iterator, bool> ret;  
        ret = m.insert(make_pair(fruits[i], 1));  
        if (ret.second == false)  
            ret.first->second++;  
    }  
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

现在走到这里已经全部插入了,那接下来我们就需要找前K个最喜欢的水果了。

思路一: 
将统计好的数据全部放入一个vector中,并且利用排序算法sort进行排序。而其默认为升序,最大的则位于数组后边,但是我们并不知道vector有多大。所以,我们采用降续,这样最大的永远在vector的前列.

void GetBeginOfThreeFruits(map<string, int>& m, vector<map<string, int>::iterator>& v)  //按照水果出现的次数降续存储于v中  
{  
    map<string, int>::iterator it = m.begin();  

    while (it != m.end())  
    {  
        v.push_back(it);  
        it++;  
    }  

    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());  
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

思路二:给一个堆,这个堆只要K个大小。 
因为找出现次数最多的,所以这里给一个小堆。堆顶元素为最小的数。每一次新进来的数字和堆顶比较,如果比堆顶小则不要。比堆顶大则把堆顶pop,把这个元素插入再重新排堆。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值