特点:
迭代器:可以让算法与数据结构无关,一般都是进行对++、–、*、->、[]等指针的操作运算符进行重载,用于遍历或者自由某个模型(vector、list等),相当于模型层面的指针
仿函数:将对象当作函数来使用
迭代器可以认为是一种设计模式,按照某种方式遍历容器
一般由实现用于迭代的对象的实现者来实现简单来说就是,例如vector的迭代器应该让实现vector的人来实现,因为其知道vector的底层模型
封装迭代器的步骤:首先将迭代器用迭代的对象的数据结构封装为迭代器,然后在原类中进行改名(注意是在public访问权限下(使用typedef,并且改为Iterator)改名,这样在外面就可以创建迭代器了),最后需要在原类中实现几个返回迭代的初始位置这样的成员函数,这样迭代器构造好对象之后就可以使用这些成员函数来赋值了
注意迭代器失效:迭代器的指针所引用的空间已经被释放
可以进行头插、头删、尾插和尾删的一个伪vector
三个重要的数据结构(类)来控制deque
双端队列相当于将多个小的定量的数组进行连接,并进行维护使在外部使用的时候像一个可变的数组一样,但是操作的时候不能用指针直接进行操作,因为指针操作的是连续的空间,而双端队列底层却是一段一段的,所以双端队列的核心技术就是封装一个完美的迭代器,用来控制访问。
数据结构模型图:
中控器(map):
缓冲区:
迭代器
++
的时候会将访问的位置转到2号段的起始位置,如果当前访问的位置是3号段的起始位置,那么当迭代器--
操作的时候会将访问的位置转到2号段的末尾位置双端队列不支持随机访问
stl中栈结构和队列结构为什么要使用双端队列来实现?
红黑树(排序效率高)
平衡因子:左右子树的高度之差
每个结点都有自己的平衡因子
AVL树(平衡二叉树): 每个结点的左右子树高度差不超过1
红黑树的性质:
底层为红黑树的关联式容器:
基本操作
void TestMultimap()
{
multimap<string, string> m;
m.insert(pair<string, string>("李逵", "黑旋风"));
m.insert(pair<string, string>("李白", "诗仙"));
m.insert(pair<string, string>("李易峰", "大帅哥"));
m.insert(make_pair("李小龙", "快使用双截棍"));
m.insert(pair<string, string>("李逵","铁牛"));//multimap是支持key值重复的
multimap<string, string>::iterator it;//因为Multimap的key值是允许重复的,所以不能使用方括号进行查找,但可以使用迭代器来进行遍历
cout << "遍历:" << endl;
for (it = m.begin(); it != m.end(); ++it)
{
cout << it->second << " ";
}
cout << endl;
cout << "key值为李逵的value为:" << endl;
for (it = m.begin(); it != m.end(); ++it)//要想知道key值对应的所有的value,就需要用迭代器来遍历整个multimap
{
if (it->first == "李逵")
{
cout << '\t' << it->second << endl;
}
}
cout << endl << "查找:" << (m.find("李逵"))->second << endl;//通过find成员函数来进行查找
}
void TestMap()
{
map<string, string> m;
m.insert(pair<string, string>("李逵", "黑旋风"));//pair是键值对的模板类,map插入的参数是键值对
m.insert(pair<string, string>("李白", "诗仙"));
m.insert(pair<string, string>("李易峰", "大帅哥"));
m.insert(make_pair("李小龙", "快使用双截棍"));//make_pair另一种创建键值对的方式
m["李玉刚"] = "天籁之音";//直接进行插入
cout << m["李逵"] << endl;//通过key来查看value
}
void TestSet()
{
set<int> s;
int arr[] = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9 };
for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
{
s.insert( arr[i] );
}
cout << s.size() << endl;
set<int>::iterator it;
it = s.begin();
cout << "遍历:";
while (it != s.end())//结果为去重之后的arr数组,说明set具有去重功能
{
cout << *it << " ";
it++;
}
cout << endl;
}
void TestMultiset()
{
multiset<int> s;
int arr[] = { 0, 3, 1, 1, 6, 2, 2, 3, 4, 4, 5, 5, 0, 6, 7, 7, 8, 8, 9, 9 };
for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
{
s.insert(arr[i]);
}
cout << s.size() << endl;
set<int>::iterator it;
it = s.begin();
cout << "遍历:";
while (it != s.end())//结果为去重之后并排序的arr数组,说明multiset具有去重并排序的功能
{
cout << *it << " ";
it++;
}
cout << endl;
}
注意插入的情况:
map的插入都是先寻找key值所在树的位置
注意查找的情况:
map里面的方括号所用的是insert来重载的,并不是用find方法,因为如果所查询的key值不存在,使用find将无法返回,并且使用insert的话,如果key值不存在,它就会将这个key值插入map,并且插入一个默认的value
哈希桶(查找效率高)
map和unordered_map的区别: