红黑树 【map】、【set】的使用

关联容器:
1)map:经过排序了的二元组的集合,map中的每个元素都是由两个值组成,其中的key(键值,一个map中的键值必须是唯一的) 是在排序或搜索时使用,它的值可以在容器中重新获取;而另一个值是该元素关联的数值。
2)set:包含了经过排序了的数据,这些数据的值(value)必须是唯一的
map和set的基本原理:红黑树。

一.红黑树实现——STL中的map
1.map是一类关联式容器。它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。对于迭代器来说,可以修改实值,而不能修改key。

2.map的功能:
1)自动建立Key - value的对应(key 和 value可以是任意你需要的类型)
2)根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次。
3)快速插入Key - Value 记录
4)快速删除记录
5)根据Key 修改value记录
6)遍历所有记录

3.map对象是模板类,需要关键字和存储对象两个模板参数,这样就定义了一个用int作为索引,并拥有相关联的指向string的指针.

4.map使用:
1.数据的插入
在构造map容器后,我们就可以往里面插入数据了
1)用insert函数插入pair数据

#include <map>
#include <string>
#include <iostream>
using namespace std;

int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(pair<int, string>(1, "student_one"));
    mapStudent.insert(pair<int, string>(2, "student_two"));
    mapStudent.insert(pair<int, string>(3, "student_three"));
    map<int, string>::iterator  iter;
    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << " "<< iter->second << endl;
    }
}

2)用insert函数插入value_type数据

#include <map>
#include <string>
#include <iostream>
using namespace std;

int main()
{
    map<int, string> mapStudent;
    mapStudent.insert(map<int, string>::value_type(1, "student_one"));
    mapStudent.insert(map<int, string>::value_type(2, "student_two"));
    mapStudent.insert(map<int, string>::value_type(3, "student_three"));
    map<int, string>::iterator  iter;

    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << " " << iter->second <<endl;
    }
}

3)用数组方式插入数据

#include <map>
#include <string>
#include <iostream>
using namespace std;

int main()
{
    map<int, string> mapStudent;
    mapStudent[1] = "student_one";
    mapStudent[2] = "student_two";
    mapStudent[3] = "student_three";
    map<int, string>::iterator  iter;

    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << " " << iter->second << endl;
    }
}

以上三种用法,虽然都可以实现数据的插入,但是它们是有区别的,当然了第一种和第二种在效果上是完成一样的,用insert函数插入数据,在数据的插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是插入数据不了的,但是用数组方式就不同了,它可以覆盖以前该关键字对应的值,用程序说明

mapStudent.insert(map<int, string>::value_type (1, “student_one”));

mapStudent.insert(map<int, string>::value_type (1, “student_two”));

上面这两条语句执行后,map中1这个关键字对应的值是“student_one”,第二条语句并没有生效,那么这就涉及到我们怎么知道insert语句是否插入成功的问题了,可以用pair来获得是否插入成功,程序如下

Pair<map<int, string>::iterator, bool> Insert_Pair;

Insert_Pair = mapStudent.insert(map<int, string>::value_type (1, “student_one”));

我们通过pair的第二个变量来知道是否插入成功,它的第一个变量返回的是一个map的迭代器,如果插入成功的话Insert_Pair.second应该是true的,否则为false。

下面给出完成代码,演示插入成功与否问题:

#include <map>
#include <string>
#include <iostream>
using namespace std;

int main()
{
    map<int, string> mapStudent;
    pair<map<int, string>::iterator, bool> Insert_Pair;
    Insert_Pair = mapStudent.insert(pair<int, string>(1, "student_one"));
    if(Insert_Pair.second == true)
    {
        cout << "Insert Successfully"<< endl;
    }
    else
    {
        cout << "Insert Failure" << endl;
    }

    Insert_Pair = mapStudent.insert(pair<int, string>(1, "student_two"));
    if(Insert_Pair.second == true)
    {
        cout << "Insert Successfully" << endl;
    }
    else
    {
        cout << "Insert Failure" << endl;
    }

    map<int, string>::iterator  iter;
    for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->first << " " << iter->second << endl;
    }
    system("pause");
    return 0;
}

2.删除:
erase()
1) erase ( iterator position );
删除的是position位置的元素
2)size_type
erase ( const key_type& x );
删除的是键值所在的位置,成功为1,否则为0
3)void
erase ( iterator first, iterator last );
删除一段迭代器区间

二.set
方法:
clear() 清除所有元素
count() 返回某个值元素的个数
empty() 如果集合为空,返回true(真)
erase() 删除一段迭代器区间
find() 返回一个指向被查找到元素的 迭代器
insert() 在集合中插入元素

count():count是为了统计某个数值出现的次数,在set里面不能重复出现相同的数值,count的返回值只有0和1两个值,0表示的是不存在,1表示存在。

三.应用:统计水果出现最多次数的问题:

using namespace std;
#include<cstdlib>  
#include<set>  
#include<map>  
#include<vector>  
#include<string>  
#include<algorithm>  

//统计水果出现次数最多的前三个  
void CountTopK(vector<string>& v)
{
    map<string, int> countMap;
    for (size_t i = 0; i<v.size(); ++i)
    {
        //  第一种方法  
        //  find()遍历了一遍,insert()又重复遍历了一遍  
        //  map<string,int>::iterator ret=countMap.find(v[i]);  
        //  if(ret!=countMap.end())   //找到  
        //  {  
        //      ret->second ++;  
        //  }  
        //  else  //没找到  
        //      countMap.insert(pair<string,int>(v[i],1));  


        //  第二种方法  
        //pair<map<string,int>::iterator ,bool> ret=countMap.insert(pair<string,int>(v[i],1));  
        //if(ret.second ==false) //没插入成功,说明已有  
        //  ret.first ->second ++;  


        //  第三种方法  
        countMap[v[i]]++;
    }


    //只能统计出数量最多的一个  
    /*map<string,int>::iterator countit=countMap.begin ();
    map<string,int>::iterator max=countMap.begin ();
    while(countit!=countMap.end())
    {
    if(countit->second >max->second )
    max=countit;
    ++countit;
    }*/

    //为了统计出排在前三位置的水果  

    //第一种解法:把map的迭代器push到vector中,然后调用算法中的sort方法  
    //vector<map<string,int>::iterator > vinfos; 
    //map<string,int>::iterator countit=countMap.begin ();  
    //while(countit!=countMap.end())  
    //{  
    //    vinfos.push_back (countit);  
    //  countit++;  
    //}  
    //仿函数  
    //struct Compare  
    //{  
    //  bool operator()(map<string,int>::iterator& l,map<string,int>::iterator& r)  
    //  {  
    //      return l->second > r->second;  
    //  }  
    //};  
    //sort(vinfos.begin(),vinfos.end(),Compare()); //从大到小排列  


    //第二种解法:把pair结构插入到vector中  
    vector<pair<string, int>> vinfos(countMap.begin(), countMap.end());  
    //仿函数  
    struct Compare
    {
        bool operator()(pair<string, int>& l, pair<string, int>& r)
        {
            return l.second > r.second;
        }
    };

    sort(vinfos.begin(), vinfos.end(), Compare()); //从大到小排列  

}
int main()
{
    vector<string> v;

    v.push_back("苹果");
    v.push_back("苹果");
    v.push_back("香蕉");
    v.push_back("苹果");
    v.push_back("苹果");
    v.push_back("梨");
    v.push_back("梨");
    v.push_back("苹果");
    v.push_back("苹果");
    v.push_back("苹果");
    v.push_back("苹果");
    v.push_back("梨");

    //给it指向的位置插入“西瓜”,其他的依次向后拷贝,size+1  
    /*vector<string>::iterator  it=v.begin();
    it++;
    v.insert(it,"西瓜");*/

    CountTopK(v);
    system("pause");
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值