STL结合容器之map/multimap详解

1. STL结合容器中的map/multimap容器

 

STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称。它是由Alexander Stepanov、Meng Lee和David R Musser在惠普实验室工作时所开发出来的。现在虽说它主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间。

STL的代码从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模版函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。

在C++标准中,STL被组织为下面的13个头文件:<algorithm>、<deque>、<functional>、<iterator>、<vector>、<list>、<map>、<memory>、<numeric>、<queue>、<set>、<stack>和<utility>

STL提供了很多种容器,每种容器都提供一组操作行为即算法接口。结合容器是STL提供的容器中的一种,其中的元素 都是经过排序的,它主要通过关键码的方式来提高查询的效率。结合容器包括set、multiset、map、multimap、hash table。

 


1.1 map/multimap的基本概念

map对象按照顺序存储一组值,其中每一个元素与一个检索关键码关联。map与set和multiset不同,set和multiset中元素既被作为存储的数据,又被作为数据的关键码,而map类型中的元素的数据和关键码是分开的。

map/multimap默认的构造函数和拷贝构造函数:

map<T1, T2> mapTT;//map默认构造函数:

map(const map &mp);//拷贝构造函数

创建一个list对象,可以通过一些方式:

1) std::map<key,type,predicate> name; //创建一个map对象

2) std::map<key,type,predicate> name(mymap); //这种方法使用了复制构造函数,从一个已存在的映射mymap中生成一个map对象。

3) std::map<key,type,predicate> name(first,last); //这种方法范围的元素中根据多重指示器所指示的起始和终止位置创建一个map。

注:Multimap和map的操作类似,唯一区别multimap键值可重复。

1.2 map/multimap的特点

a. map和multimap的底层实现是红黑树。

b. map和multimap的元素不可随机存取,但元素搜寻速度很快。

c. Map所有的元素都是pair,同时拥有实值和键值.

d.pair的第一元素被视为键值,第二元素被视为实值.

e.map不允许两个元素有相同的键值,multimap键值可以重复。

f.我们不可以通过map的迭代器改变map的键值,可以改变实值。

 

1.3 map/multimap的迭代器

map/multimap有定义自己的迭代器。

迭代器的用法如下:

	multimap<int, worker>::iterator itw = plist.find(myoperate);
	int depatCount = plist.count(myoperate);
	int num = 0;
	if (itw != plist.end())
	{
		while ((itw != plist.end()) && (num < depatCount))
		{
			cout << "姓名:" << itw->second.name << "年龄:" << itw->second.age << "工资:" << itw->second.salary << "电话:" << itw->second.tele << endl;
			itw++;
			num++;
		}
	}

 

1.4 map/multimap的数据结构

map/multima的底层实现是红黑树,一个map对象像链表一样顺序的存储一组值。

Map和list拥有相同的某些性质,当对它的容器元素进行新增操作或者删除操作时,操作之前的所有迭代器,在操作完成之后依然有效,当然被删除的那个元素的迭代器必然是个例外

map的使用场景:比如按ID号存储十万个用户,想要快速要通过ID查找对应的用户。二叉树的查找效率,这时就体现出来了。如果是vector容器,最坏的情况下可能要遍历完整个容器才能找到该用户。

 

1.5 map/multimap的常用API

函数说明
begin()返回指向集合中第一个元素的迭代器
clear()删除集合中所有元素
empty()如果集合为空,则返回为true值

end

返回指向集合中最后一个元素的迭代器
erase(start,end)删除迭代器start和end所管辖范围内的集合元素
erase(x)删除集合中值为x的元素
equal_range(x)返回表示x下界和上界的两个迭代器,下界表示集合中有一个值等于x的元素,上界表示第一个值大于x的元素
inser(map)把map类型或者pair插入集合中
find(x)返回一个指向x的迭代器。如果x不存在,返回的迭代器等于end
lower_bound(x)返回一个迭代器,指向位于x之前且紧邻x的元素。
max_size()返回集合的最大容量
upper_bound(x)返回一个指向x的迭代器
push_front(x)把x放到链表的开始
rbegin返回一个反向迭代器,指向链表末尾元素之后
rend返回一个反向迭代器,指向链表起始元素
size()返回链表的大小(元素的个数)
swap(list)交换两个集合的内容
value_comp返回value_compare类型的对象,该对象用于判断集合中元素的先后顺序

map/multimap的接口的应用实例(接口用红色标记):

//创建5个员工
void CreateWorker(vector<worker>& vlist)
{
    string seed = "ABCDE";
    for (int i = 0; i < 5; i++)
    {
        worker p;
        p.name = "员工";
        p.name += seed[i];
        p.age = rand() % 30+20;
        p.salary = rand() % 20000 + 10000;
        p.tele = "123145646";
        vlist.push_back(p);

    }
}

//5名员工分配到不同的部门
void WorkerByGroup(vector<worker>& vlist, multimap<int, worker>& plist)
{
    int operate = -1;//用户的操作
    for (vector<worker>::iterator it = vlist.begin(); it != vlist.end(); it++)
    {
        cout << "当前员工信息:" << endl;
        cout << "姓名:" << it->name << "年龄:" << it->age << "工资:" << it->salary << "电话:" << it->tele << endl;
        cout << "请对该员工进行部门分配(1 销售部门,2 研发部门, 3 财务部门):" << endl;
        //scanf("%d", &operate);
        cin >> operate;

        while (true)
        {
            if (operate == SALE_DEPATMENT)
            {
                plist.insert(make_pair(SALE_DEPATMENT,*it));
                break;
            }
            else if (operate == DEVELOP_DEPATMENT)
            {
                plist.insert(make_pair(DEVELOP_DEPATMENT,*it));
                break;
            }
            else if (operate == FINACIAL_DEPATMENT)
            {
                plist.insert(make_pair(FINACIAL_DEPATMENT, *it));
                break;
            }
            else
            {
                cout << "您的输入有误,请重新输入(1 销售部门,2 研发部门, 3 财务部门):" << endl;
                //scanf("%d",&operate);
                cin >> operate;

            }
        }
    }
    cout << "员工部门分配完毕" << endl;
    cout << "********************" << endl;
}


//打印员工信息
void printList(multimap<int, worker>& plist, int myoperate)
{
    if (myoperate == ALL_DEPATMENT)
    {
        for (multimap<int, worker>::iterator it = plist.begin(); it != plist.end(); it++)
        {
            cout << "姓名:" << it->second.name << "年龄:" << it->second.age << "工资:" << it->second.salary << "电话:" << it->second.tele << endl;
        }
        return;
    }

    multimap<int, worker>::iterator itw = plist.find(myoperate);
    int depatCount = plist.count(myoperate);
    int num = 0;
    if (itw != plist.end())
    {
        while ((itw != plist.end()) && (num < depatCount))
        {
            cout << "姓名:" << itw->second.name << "年龄:" << itw->second.age << "工资:" << itw->second.salary << "电话:" << itw->second.tele << endl;
            itw++;
            num++;
        }
    }
}

//根据用户操作显示不同部门的人员列表
void ShowWorkerList(multimap<int, worker>& plist, int myoperate)
{
    switch (myoperate)
    {
        case SALE_DEPATMENT:
            printList(plist,SALE_DEPATMENT);
            break;
        case DEVELOP_DEPATMENT:
            printList(plist, DEVELOP_DEPATMENT);
            break;
        case FINACIAL_DEPATMENT:
            printList(plist, FINACIAL_DEPATMENT);
            break;
        case ALL_DEPATMENT:
            printList(plist, SALE_DEPATMENT);
            break;

    }
}


//用户操作菜单
void WorkerMenue(multimap<int, worker>& plist)
{
    int flag = -1;
    int isexit = 0;
    while (true)
    {
        cout << "请输入您的操作(1 销售部门,2 研发部门, 3 财务部门):" << endl;
        //scanf("%d",&flag);
        cin >> flag;

        switch (flag)
        {
            case SALE_DEPATMENT:
                ShowWorkerList(plist, SALE_DEPATMENT);
                break;
            case DEVELOP_DEPATMENT:
                ShowWorkerList(plist, DEVELOP_DEPATMENT);
                break;
            case FINACIAL_DEPATMENT:
                ShowWorkerList(plist, FINACIAL_DEPATMENT);
                break;
            case ALL_DEPATMENT:
                ShowWorkerList(plist, SALE_DEPATMENT);
                break;
            case 0:
                isexit = 1;
                break;
            default:
                cout << "您输入的有误,请重新输入" << endl;
                break;

        }
        if (isexit == 1)
        {
            break;
        }
    }
}




 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值