使得对数据结构的添加、删除、查找操作复杂度都限制在log(n)中,在STL中体现为multiset set multimap map四种排序容器中
multiset set 头文件:
multimap map 头文件:
文章涉及multiset set multimap map几种容器的遍历方法:只能借助于迭代器
multiset::iterator p;
p是迭代器,相当于指针,可++,–,用!=和==比较,不可以比较大小,不可以加减整数,不能相减(与指针不一样,有些容器几乎跟指针一模一样)
multiset
multisetst; 能自动排序,开始st为空
排序规则:表达式"a<b"为true,则a排在b前面(相当于从小到大的顺序排列)
添加元素:st.insert()
查找元素:st.find()
删除元素:st.erase()
multiset<int>st;
int a[10] = { 2,6,7,3,9,5,6,8,3,9 };
for (int i = 0; i < 10; i++)
{
st.insert(a[i]);
}
multiset<int>::iterator i; //容器借助迭代器遍历元素,相当于指针
for (i = st.begin(); i != st.end(); i++)
cout << *i << " ";
cout << endl;
//输出:2 3 3 5 6 6 7 8 9 9 排好序的
i= st.find(2); //find 返回值为指向要查找元素的迭代器,若元素不存在就指向end()
if (i == st.end()) cout << "Not Found" << endl;
else cout << *i << endl;
multiset可以自定义排序规则
multiset<int, greater>st----------排序规则为从大到小
multiset<int ,Rule()>st;-----------自定义排序规则
find(x):在排序容器中找一个y,使得“x必须排在y”和“y必须排在x前面”都不成立,不是一般的"==",要按照排序规则来分析
set
set和multiset的区别在于容器里不能有重复元素
a和b重复:“a必须排在b前面”和“b必须排在a前面”都不成立
set插入元素可能不成功(不能插入容器中已经有的元素)
set的用法:
set<int>my_set;
int a[6]={4,7,4,9,7,6};
for(int i=0;i<6;i++)
my_set.insert(a[i]);
set<int>::iterator i;
for(i=my_set.begin();i!=my_set.end();i++)
cout<<*i<<" "; //输出4 6 7 9 无重复元素
cout<<endl;
//由于set很可能插入不成功,所以插入元素以后需要判断
pair<set<int>::iterator,bool>res=my_set.insert(8);
/*
pair这个数据类型相当于
struct pair
{
set<int>::iterator first; //返回指向插入元素位置的迭代器
bool second; //返回插入是否成功
含有两个数据成员,分别为pair<T1,T2> 的两个变量T1,T2;
}
*/
if(!res.second) cout<<*res.first<<"already exists"<<endl;
else cout<<*res.first<<"inserted"<<endl;
multimap
multimap容器里的元素,都是pair形式的,
multimap<T1,T2>mp;
struct
{
T1 first; //关键字(键)
T2 second; //值
};
mulrimap中的元素按照first排序,并可以按first进行查找,缺省的排序规则是"a.first <b.first" 为true,则a排在b前面
适用于需要频繁添加、删除元素,查找元素的程序,并且元素一直都是有序的,使用multimap效率高
案例:学生成绩录入,包含学生姓名、学生学号,学生成绩,学生学号是唯一的,姓名和分数都不唯一,程序有两种输入,分别为添加信息"Add name id score"和查询信息"Query score"交替出现,查询信息时为查询小于输入分数的最大分数对应学生的信息,如果有多个符合条件的信息输出学号最大的那个
由于程序需要不断的添加信息和查询信息,为了数据更大时的效率更高并且是以分数为关键字进行查询,则选择multimap数据结构
#include<bits/stdc++.h>
#include<map> //multimap 和map需要包含的头文件
using namespace std;
struct Info //定义学生信息结构体
{
string name;
int id;
};
struct Stu //定义分数(关键字)-- 信息(值)结构体,相当于multimap类型
{
int score;
Info info;
};
typedef multimap<int,Info> MAP;
int main()
{
MAP mp;
Stu stu;
char cmd[20];
while(cin>>cmd)
{
if(cmd[0]=='A')
{
cin>>stu.info.name>>stu.info.id>>stu.score;
mp.insert(make_pair(stu.score,stu.info));
//make_pair生成一个pair<int,Info> 变量
//其first等于st.score,second等于st.info
}
else if(cmd[0]=='Q')
{
int score;
cin>>score;
MAP::iterator p=mp.lower_bound(score); //用lower_bound来查找比score低的最大的分数对应的学生信息
//表示[bgein(),p) 的学生分数都比score低,但是p所指向的不会比score低(大于等于score)
if(p!=mp.begin()) //表示找到了满足条件的学生
{
p--; //从第一个满足条件的学生开始遍历
int sco=p->first;
int max=p->second.id;
MAP::iterator t_mp=p;
while((p!=mp.begin())&&(p->first==sco)) //遍历所有分数相同的学生
{
if(p->second.id>max)
{
t_mp=p;
max=p->second.id;
}
p--;
}
cout<<t_mp->second.name<<" "<<t_mp->second.id<<" "<<t_mp->first;
} //不能直接写t_mp->info(不存在这个数据成员,要写t_mp->second);
else cout<<"not found"<<endl; //表示没有比score低的学生
}
}
return 0;
}
map
不能有关键字重复的元素,重复元素表示两个个元素谁在前谁在后都可以
可以使用[],下标为关键字,返回值为first和关键字相同的元素的second(通过关键字查值)
插入元素可能失败,因为可能关键字已经存在了
更多内容参见这篇文章: