C++ 标准模板库STL,是一个使用模板技术实现的通用程序库,该库由容器container,算法algorithm,迭代器iterator,容器和算法之间通过迭代器进行无缝连接,其中所包含的数据结构都是目前最优解,该库既能保证软件代码的高可复用性,又能保证代码具有相当高的执行效率,STL库是ANSI/ISO的C++标准的具体实现,任何标准库的实现都是以源码形式释出的.
STL是C++的一部分,STL可分为容器(containers)、迭代器(iterators)、空间配置器(allocator)、配接器(adapters)、算法(algorithms)、仿函数(functors)六个部分,以下案例主要是在学习时对容器的总结笔记,基本上涵盖了关于容器之间,能够想到的任何操作,一次性全部涵盖其中。
String 字串操作容器 String字符串操作容器是C++标准中实现的一个重要容器,其主要用于对字符串的高效处理,它和C风格中的string.h
并不是同一个库,两个库有极大的差距,C库中的string.h
主要面向过程提供一些处理函数,而C++库中的string
则是基于类实现的更高效的一种字符串处理方法集,类中提供了非常方便的成员函数供我们使用.
字符串构造函数: 因为字符串关键字其实是一个类,我们可以通过构造函数完成初始化字符串.
#include <iostream> #include <string> using namespace std;int main (int argc, char * argv[]) { string str ("hello lyshark" ) ; string str_1 (str) ; string str_2 (str, 2 , 5 ) ; string str_3 (str.begin(), str.end()) ; char ch[] = "lyshark" ; string str_4 (ch, 3 ) ; string str_5 (5 , 'x' ) ; system ("pause" ); return 0 ; }
字符串对象赋值: 使用String对象中的assign()
函数,可以实现字符串之间的赋值.
#include <iostream> #include <string> using namespace std;int main (int argc, char * argv[]) { string str,new_str; str = "lyshark" ; new_str.assign (str); string s1, s2, s3; s1.assign (str, 1 , 4 ); s2.assign (5 , 'A' ); cout << s3 << endl; system ("pause" ); return 0 ; }
字符串遍历操作: 通过使用str.size()
函数获取到字符的具体个数,最后循环遍历输出这些字符串.
#include <iostream> #include <string> #include <stdexcept> using namespace std;int main (int argc, char * argv[]) { string str = "hello lyshark" ; for (int x = 0 ; x < str.size (); x++) cout << str[x] << endl; try { for (int x = 0 ; x < str.size (); x++) cout << str[x] << endl; } catch (out_of_range &e) { cout << "异常类型: " << e.what () << endl; } system ("pause" ); return 0 ; }
字符串添加与删除: 使用append()
添加字符串,使用insert()
插入字符串,使用erase()
删除指定范围字符串.
#include <iostream> #include <string> using namespace std;int main (int argc, char * argv[]) { string str1 ("hello " ) , str2 ("lyshark" ) ; str1.append (str2); str1.append (str2, 1 , 3 ); str1.append (5 , 'A' ); string str3 = "this is ok" ; string str4 = str3.substr (1 ,3 ); string str5 = str3.substr (1 , 5 ); string str6 = "real steel" ; str6.erase (5 ); str6.erase (0 , 4 ); string str7 = "hello lyshark" ; str7.insert (2 , "123" ); str7.insert (3 , 4 , 'A' ); system ("pause" ); return 0 ; }
字符串查找与替换: 使用find()
可查找字符串第一次出现的位置,使用compare
比较字符串,使用replace()
替换字符串.
#include <iostream> #include <string> using namespace std;int main (int argc, char * argv[]) { string str1 ("Source Code" ) ,str2 ("Source Code" ) ; int x; if ((x = str1.find ("u" )) != string::npos) cout << str1.substr (x) << endl; if ((x = str1.find ("Source" , 3 )) != string::npos) cout << str1.substr (x) << endl; if ((x = str1.find_first_of ("urc" )) != string::npos) cout << x << endl; if (str1.compare (str2)) cout << "False" << endl; string str3 = "hello lyshark" ; str3.replace (1 , 3 , "abcde" ); cout << str3 << endl; system ("pause" ); return 0 ; }
字符串首尾数据提取: 我们可以通过find()
查找指定通配符,然后使用substr()
灵活的提取左面或右面的字符串.
#include <iostream> #include <string> using namespace std;int main (int argc, char * argv[]) { string email = "admin@blib.cn" ; int pos = email.find ("@" ); string username = email.substr (0 , pos); cout << username << endl; string mail = email.substr (pos+1 ); cout << mail << endl; system ("pause" ); return 0 ; }
字符串与字符互转: 使用str.c_str()
将string转换为char,使用string str()
将char强转为string.
#include <iostream> #include <string> using namespace std;int main (int argc, char * argv[]) { string str = "lyshark" ; const char *ptr = str.c_str (); cout << ptr << endl; string str1 (ptr) ; cout << str1 << endl; int Num = 546 ; string str2 = to_string (Num); cout << str2 << endl; system ("pause" ); return 0 ; }
字符串大小写互转: 使用topper()
将小写字符变成大写,使用tolower()
将大写字符变为小写.
#include <iostream> #include <string> using namespace std;int main (int argc, char * argv[]) { string str = "lyshark" ; for (int x = 0 ; x < str.size (); x++) str[x] = toupper (str[x]); cout << str << endl; system ("pause" ); return 0 ; }
Vector 数组向量容器 Vector 容器是一种简单的高效率的数组容器,该容器可以方便、灵活地代替数组,容器可以实现动态对数组阔扩容删除等各种复杂操作,其时间复杂度O(l)常数阶
,其他元素的插入和删除为O(n)线性阶
,其中n为容器的元素个数,vector具有自动的内存管理机制,对于元素的插入和删除可动态调整所占用的内存空间.
数组向量的基本使用: 首先我们来实现遍历数组向量,向数组向量中放入元素与移出元素.
#include <iostream> #include <algorithm> #include <vector> using namespace std;void MyPrint (vector<int >& var) { cout << "empty = " << var.empty () << " --> size = " << var.size () << endl; cout << "capacity = " << var.capacity () << " --> max_size = " << var.max_size () << endl; for_each(var.begin (), var.end (), [](int val){ cout << val << endl; }); cout << "---------------------------------------------------------" << endl; } int main (int argc, char * argv[]) { vector<int > var{ 1 , 2 , 3 }; var.push_back (4 ); MyPrint (var); var.pop_back (); MyPrint (var); var.resize (10 ); var.reserve (30 ); MyPrint (var); system ("pause" ); return 0 ; }
数组向量的正/反向遍历: 前两种遍历方式分别是通过下标法和迭代实现正向遍历,最后的第三种方式是实现的反向遍历.
#include <iostream> #include <string> #include <vector> using namespace std;int main (int argc, char * argv[]) { vector<string> str_array{ "admin" , "guest" , "lyshark" }; cout << "str_array sizeof:" << str_array.capacity () << endl; for (int x = 0 ; x < str_array.size (); x++) { cout << "str_array --> " << str_array[x] << endl; } cout << endl; vector<int > int_array{ 1 , 2 , 3 , 4 , 5 }; vector<int >::const_iterator item; int each = 0 ; for (item = int_array.begin (), each = 0 ; item != int_array.end (); ++item, ++each) { cout << "int_array[" << each << "] --> " << (*item) << endl; } cout << endl; vector<int > rint_array{ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 }; vector<int >::reverse_iterator start, end; end = int_array.rend (); for (start = int_array.rbegin (); start != end; start++) { cout << "int_array --> " << *start << endl; } system ("pause" ); return 0 ; }
数组向量的正/反向排序: 首先生成10个随机数,然后分别对这些数字进行正向排序,与反向排序.
#include <iostream> #include <vector> #include <algorithm> using namespace std;bool MyCompare (int value1, int value2) { return value1 > value2; }int main (int argc, char * argv[]) { vector<int > *int_array = new vector<int >; for (int x = 0 ; x < 10 ; x++) int_array->push_back (rand () % 100 ); std::sort (int_array->begin (), int_array->end ()); vector<int >::const_iterator item = int_array->cbegin (); while (item != int_array->cend ()) { cout << (*item) << " " ; item++; } cout << endl; std::sort (int_array->begin (), int_array->end (), MyCompare); vector<int >::const_iterator item_1 = int_array->cbegin (); while (item_1 != int_array->cend ()) { cout << (*item_1) << " " ; item_1++; } system ("pause" ); return 0 ; }
向数组向量中插入元素: 向数组中插入元素可以使用push_back()
方法,当需要插入到指定位置时可使用insert()
方法.
#include <iostream> #include <string> #include <vector> using namespace std;int main (int argc, char * argv[]) { vector<string> str_array{ "admin" , "guest" , "lyshark" }; str_array.push_back ("django" ); str_array.push_back ("python" ); str_array.pop_back () str_array.insert (str_array.begin () + 2 , "ruby" ); str_array.insert (str_array.end (), "C++" ); for (int x = 0 ; x < str_array.size (); x++) cout << "str_array[" << x << "] --->" << str_array[x] << endl; system ("pause" ); return 0 ; }
向数组向量中插入结构指针: 首先我们定义一个数组向量,然后向指定的数组中插入结构的首地址.
#include <iostream> #include <vector> using namespace std;typedef struct { int ID; char szName[20 ]; }Person, *Ptr; int main (int argc, char * argv[]) { vector<Person> ary[10 ]; Person p1 = { 1 , "admin" }; Person p2 = { 2 , "lyshark" }; Person p3 = { 3 , "guest" }; ary[0 ].push_back (p1); ary[1 ].push_back (p2); ary[2 ].push_back (p3); for (int x = 0 ; x < 3 ; x++) { vector<Person>::iterator item = ary[x].begin (); cout << "ID: " << (*item).ID <<" ---> Name: " << (*item).szName << endl; } system ("pause" ); return 0 ; }
向数组向量中插入类指针: 此处插入类指针与上方的结构指针是类似的,此处不在说明了.
#include <iostream> #include <vector> using namespace std;class MyAnimal {public : char *name; int id; public : MyAnimal (char * name, int id) { this ->name = name; this ->id = id; } }; int main (int argc, char * argv[]) { MyAnimal* pDog = new MyAnimal ("dog" , 1 ); MyAnimal* pMonkey = new MyAnimal ("monkey" , 2 ); MyAnimal* pSnake = new MyAnimal ("psnake" , 3 ); vector<MyAnimal *> var; var.push_back (pDog); var.push_back (pMonkey); var.push_back (pSnake); vector<MyAnimal*>::iterator start, end; end = var.end (); for (start = var.begin (); start != end; start++) { cout <<"ID: " <<(*start)->id << " ---> " << "Name: " << (*start)->name << endl; } system ("pause" ); return 0 ; }
在数组容器中嵌套容器: 首先声明var
容器,该容器的内部定义为容器类型,然后初始化v1,v2,将其放入var容器中.
#include <iostream> #include <vector> using namespace std;int main (int argc, char * argv[]) { vector< vector<int > > var; vector<int > v1; vector<int > v2; for (int x = 0 ; x < 5 ; x++) { v1.push_back (x); v2.push_back (x + 10 ); } var.push_back (v1); var.push_back (v2); for (vector<vector<int >>::iterator item = var.begin (); item != var.end (); item++) { for (vector<int >::iterator vitem = (*item).begin (); vitem != (*item).end (); vitem++) { cout << (*vitem) << " " ; } cout << endl; } system ("pause" ); return 0 ; }
函数参数定义为容器类型: 这里我们定义了函数MyPrintVector()
其形参可接受vector<int>
类型的容器.
#include <iostream> #include <vector> using namespace std;void MyPrintVector (vector<int > &var) { for (vector<int >::iterator item = var.begin (); item != var.end (); item++) { cout << (*item) << " " ; } cout << endl; } int main (int argc, char * argv[]) { vector <int > var; int arry[] = { 1 , 2 , 3 , 4 , 5 }; vector<int > v1 (arry, arry + sizeof (arry) / sizeof (int )) ; vector<int > v2 (v1.begin(), v1.end()) ; MyPrintVector (v2); vector<int > v3 (10 , 20 ) ; MyPrintVector (v3); vector<int > v4; v4.assign (v3.begin (), v3.end ()); MyPrintVector (v4); v4.swap (v2); MyPrintVector (v4); system ("pause" ); return 0 ; }
数组向量元素的删除: 数组向量并没有直接删除元素的方法,需要使用find()
方法找到元素,迭代并使用erase()
删除元素.
#include <iostream> #include <vector> #include <algorithm> using namespace std;int main (int argc, char * argv[]) { vector<int > int_array {1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 }; vector<int >::iterator item = find (int_array.begin (), int_array.end (), 7 ); if (item != int_array.cend ()) int_array.erase (item); vector<int >::iterator start, end; end = int_array.end (); for (start = int_array.begin (); start != end; start++) { cout << (*start) << endl; } system ("pause" ); return 0 ; }
Deque 双向队列容器 Deque双向队列容器与Vector非常相似,它不但可以在数组尾部插入和删除元素,还可以在头部进行插入和删除,队列算法的时间复杂度也是常数阶O(1)
,队列内部的数据机制和性能与Vector不同,一般来说当考虑到容器元素的内存分配策略和操作的性能时,Deque相对于Vector较有优势.
单向队列的基本操作: 单向队列容器遵循先进先出FIFO的原则,最先从队列尾部插入的容器会最先被弹出队列.
#include <iostream> #include <queue> using namespace std;int main (int argc, char * argv[]) { queue<int > que; que.push (1 ); que.push (2 ); while (!que.empty ()) { cout << "Head: " << que.front () << endl; cout << "End: " << que.back () << endl; que.pop (); } cout << "Size: " << que.size () << endl; system ("pause" ); return 0 ; }
双向队列的基本操作: 双向队列相比于单项来说,它的前面后面都可以插入和取出数据,但同样遵循FIFO原则.
#include <iostream> #include <deque> using namespace std;int main (int argc, char * argv[]) { deque<int > deq{ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }; deq.push_back (11 ); deq.push_front (12 ); deq.pop_back (); deq.pop_front (); cout << "是否为空: " << deq.empty () << endl; cout << "首个元素: " << deq.front () << endl; cout << "末尾元素: " << deq.back () << endl; cout << "元素个数: " << deq.size () << endl; cout << "最大元素数: " << deq.max_size () << endl; system ("pause" ); return 0 ; }
双向队列正/反向遍历: 通过使用下标法和迭代器都可以实现对队列的数据遍历,这里先演示正向遍历,然后反向遍历.
#include <iostream> #include <deque> using namespace std;int main (int argc, char * argv[]) { deque<int > deq{ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }; for (int x = 0 ; x < deq.size (); x++) cout << deq[x] << " " ; cout << endl; deque<int >::iterator start, end; end = deq.end (); for (start = deq.begin (); start != end; start++) cout << (*start) << " " ; cout << endl; deque<int >::reverse_iterator rstart, rend; rend = deq.rend (); for (rstart = deq.rbegin (); rstart != rend; rstart++) { cout << (*rstart) << " " ; } system ("pause" ); return 0 ; }
双向队列插入/弹出元素: 通过使用insert()
向队列中插入元素,使用erase()
可以弹出指定位置的元素.
#include <iostream> #include <deque> using namespace std;int main (int argc, char * argv[]) { deque<int > deq{ 1 , 2 , 3 , 4 , 5 }; deq.push_back (6 ); deq.push_front (0 ); deq.insert (deq.begin () + 1 , 9 ); deq.pop_front (); deq.pop_back (); deq.erase (deq.begin () + 1 ); for (int x = 0 ; x < deq.size (); x++) cout << deq[x] << " " ; cout << endl; system ("pause" ); return 0 ; }
函数参数传递双向队列: 将我们定义的deque<int> deq
的指针传递给PrintDeque
这个函数进行迭代遍历.
#include <iostream> #include <deque> #include <algorithm> using namespace std;void PrintDeque (const deque<int > &deq) { for (deque<int >::const_iterator item = deq.begin (); item != deq.end (); item++) { cout << (*item) << endl; } } int main (int argc, char * argv[]) { deque<int > deq = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 }; PrintDeque (deq); system ("pause" ); return 0 ; }
List/Slist 动态链表容器 List双向链表是一种序列容器,它的数据元素可以通过链表指针串接成逻辑意义上的线性表,不同于采用线性表顺序存储结构的Vector和Deque容器,双向链表中任一位置的元素,查找,插入和删除,都具有高效的常数阶算法时间复杂度O(1).
List的缺点是无法通过位置来直接访问序列中的元素,也就是说,不能动态跨段索引元素.为了访问 list 内部的一个元素,必须一个一个地遍历元素,通常从第一个元素或最后一个元素开始遍历.
双向链表遍历整数: 首先动态生成一个链表,里面存储1-10之间的数,然后通过链表指针开始遍历这个数值链表.
#include <iostream> #include <list> using namespace std;int main (int argc, char * argv[]) { list<int > MyList; for (int x = 0 ; x < 10 ; x++) MyList.push_back (x); list<int >::_Nodeptr node = MyList._Myhead->_Next; for (int x = 0 ; x < MyList._Mysize; x++) { cout << "Node: " << node->_Myval << endl; node = node->_Next; if (node == MyList._Myhead) { node = node->_Next; } } system ("pause" ); return 0 ; }
双向链表遍历结构体: 上方遍历的是一个整数链表,接下来实现的是遍历Student
这个结构体中的所有数据.
#include <iostream> #include <list> using namespace std;struct Student { char * name; int age; char * city; }; bool MyCompare (Student &s1, Student &s2) { if (s1.age > s2.age) return true ; return false ; } int main (int argc, char * argv[]) { Student stu[] = { { "admin" , 22 , "beijing" }, { "lisi" , 32 , "shanghai" }, { "wangwu" , 26 , "shandong" }, {"wangermazi" ,8 ,"jinan" } }; list<Student> MyList; MyList.push_back (stu[0 ]); MyList.push_back (stu[1 ]); MyList.push_back (stu[2 ]); MyList.push_back (stu[3 ]); MyList.sort (MyCompare); list<Student>::iterator start, end; for (start = MyList.begin (); start != MyList.end (); start++) { cout << (*start).name << " " ; cout << (*start).age << " " ; cout << (*start).city << endl; } system ("pause" ); return 0 ; }
实现正反向遍历链表: 链表容器不支持随机访问只能遍历,使用begin()/end()
正向遍历,使用rbegin()/rend()
反向遍历.
#include <iostream> #include <list> using namespace std;int main (int argc, char * argv[]) { list<int > MyList{ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 }; for (list<int >::iterator item = MyList.begin (); item != MyList.end (); item++) cout << *item << endl; for (list<int >::reverse_iterator item = MyList.rbegin (); item != MyList.rend (); item++) cout << *item << endl; system ("pause" ); return 0 ; }
遍历链表中指定元素: 通过使用结构体存储人物数据,然后使用迭代器查找id=3
的人物结构,找到后输出它的Name
属性.
#include <iostream> #include <list> #include <string> using namespace std;struct Student { int id; string name; }; int main (int argc, char * argv[]) { list<Student> MyList; Student stu[] = { { 1 ,"aaddm" }, { 2 ,"admin" }, { 3 ,"waann" }, { 4 ,"ruiii" } }; for (int x = 0 ; x < 4 ; x++) { MyList.push_back (stu[x]); } list<Student>::iterator start, end; for (start = MyList.begin (); start != MyList.end (); start++) { if ((*start).id == 3 ) { cout << "UName: " << (*start).name << endl; } } system ("pause" ); return 0 ; }
实现插入/删除链表元素: 定义list<int>
链表,通过insert()
向链表中插入元素,通过remove()
移除指定的元素.
#include <iostream> #include <list> using namespace std;void MyPrint (list<int > &MyList) { list<int >::iterator start, end; for (start = MyList.begin (); start != MyList.end (); start++) cout << *start << " " ; cout << endl; } int main (int argc, char * argv[]) { list<int > MyList{ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 }; MyList.push_back (10 ); MyList.push_front (0 ); MyList.pop_front (); MyList.pop_back (); MyList.insert (MyList.begin (), 500 ); MyList.insert (MyList.end (), 1000 ); MyList.remove (7 ); MyPrint (MyList); system ("pause" ); return 0 ; }
实现整数链表正反向排序: 定义list<int>
链表,并通过sort()
实现正反向排序,通过reverse()
实现链表翻转.
#include <iostream> #include <list> using namespace std;void MyPrint (list<int > &MyList) { list<int >::iterator start, end; for (start = MyList.begin (); start != MyList.end (); start++) cout << *start << " " ; cout << endl; } bool MyCompare (int value1, int value2) { return value1 > value2; }int main (int argc, char * argv[]) { list<int > MyList{ 12 ,56 ,33 ,78 ,9 ,43 ,2 ,1 ,7 ,89 }; MyList.reverse (); MyPrint (MyList); MyList.sort (); MyPrint (MyList); MyList.sort (MyCompare); MyPrint (MyList); system ("pause" ); return 0 ; }
实现类链表正反向排序: 定义Person类存储数据,使用sort()
函数设置自定义回调函数MyCompare()
实现对类中数据排序.
#include <iostream> #include <list> #include <string> using namespace std;class Person { public : string m_name; int m_age; int m_height; public : Person (string name, int age, int height){ this ->m_name = name; this ->m_age = age; this ->m_height = height; } }; bool MyCompare (Person &x,Person &y) { if (x.m_age == y.m_age) return x.m_height < y.m_height; else return x.m_age > y.m_age; } int main (int argc, char * argv[]) { list<Person> MyList; Person p1 ("a" , 20 , 169 ) ; Person p2 ("b" , 14 , 155 ) ; Person p3 ("c" , 14 , 165 ) ; MyList.push_back (p1); MyList.push_back (p2); MyList.push_back (p3); MyList.sort (MyCompare); for (list<Person>::iterator it = MyList.begin (); it != MyList.end (); it++) cout << "Name: " << it->m_name << " Age: " << it->m_age << " Height: " << it->m_height << endl; system ("pause" ); return 0 ; }
实现类链表成员的删除: 自定义Person结构来存储人物的信息,然后重载等于号,实现让remove可以删除Person中的数据.
#include <iostream> #include <list> #include <string> using namespace std;class Person { public : string m_name; int m_age; int m_height; public : Person (string name, int age, int height){ this ->m_name = name; this ->m_age = age; this ->m_height = height; } public : bool operator ==(const Person &p) { if (this ->m_name == p.m_name && this ->m_age == p.m_age && this ->m_height == p.m_height) return true ; return false ; } }; int main (int argc, char * argv[]) { list<Person> MyList; Person p1 ("a" , 20 , 169 ) ; Person p2 ("b" , 14 , 155 ) ; Person p3 ("c" , 34 , 165 ) ; MyList.push_back (p1); MyList.push_back (p2); MyList.push_back (p3); MyList.remove (p3); for (list<Person>::iterator it = MyList.begin (); it != MyList.end (); it++) cout << "Name: " << it->m_name << " Age: " << it->m_age << " Height: " << it->m_height << endl; system ("pause" ); return 0 ; }
Set/Multiset 集合容器 Set集合使用的是红黑树的平衡二叉检索树的数据结构,来组织泛化的元素数据,通常来说红黑树根节点每次只能衍生出两个子节点,左面的节点是小于根节点的数据集合,右面的节点是大于根节点的集合,通过这样的方式将数据组织成一颗看似像树一样的结构,而平衡一词的含义则是两边的子节点数量必须在小于等1的区间以内.
需要注意的是,Set集合天生去重,所有元素都会根据元素的键值自动的排序,并且Set元素在确定后无法进行更改,换句话说Set的Iterator是一种Const_iterator,而Multiset则允许出现重复的数据,如需使用只需要将set<int>
改为multiset<int>
即可,Multiset操作方式与API函数与Set集合保持相同.
正反向遍历集合元素: 通过迭代器实现对集合容器的正反向遍历,注意Set集合只能使用insert方法向集合插值.
#include <iostream> #include <set> using namespace std;void PrintSet (set<int >& s ,int flag) { if (flag == 1 ) { for (set<int >::iterator it = s.begin (); it != s.end (); it++) cout << (*it) << " " ; } else if (flag == 0 ) { for (set<int >::reverse_iterator it = s.rbegin (); it != s.rend (); it++) cout << (*it) << " " ; } } int main (int argc, char * argv[]) { set<int > var { }; var.insert (56 ); var.insert (67 ); var.insert (99 ); PrintSet (var,0 ); if (var.empty ()) cout << "None" << endl; else cout << "size: " << var.size () << endl; var.erase (var.begin ()); var.erase (99 ); PrintSet (var, 0 ); system ("pause" ); return 0 ; }
查找集合中指定元素: 通过find
可实现查找集合指定元素,lower/upper/equal bound
则实现对元素区间的遍历.
#include <iostream> #include <set> using namespace std;int main (int argc, char * argv[]) { set<int > var { 23 ,44 ,56 ,78 ,90 ,0 ,90 ,12 ,54 ,67 ,85 ,3 ,4 ,7 }; set<int >::iterator pos = var.find (90 ); if (pos != var.end ()) cout << "找到了: " << *pos << endl; int number = var.count (90 ); cout << "90是否存在: " << number << endl; set<int >::iterator it = var.lower_bound (4 ); if (it != var.end ()) cout << "找到了 lower_bound(4) 的值:" << *it << endl; set<int >::iterator it2 = var.upper_bound (4 ); if (it2 != var.end ()) cout << "找到了 upper_bound(4) 的值:" << *it2 << endl; pair<set<int >::iterator, set<int >::iterator> ret = var.equal_range (4 ); if (ret.first != var.end ()) cout << "找到 lower_bound(4): " << *(ret.first) << endl; if (ret.second != var.end ()) cout << "找到 upper_bound(4): " << *(ret.second) << endl; system ("pause" ); return 0 ; }
设置默认集合排序方式: 集合默认情况下会从小到大的将数据排列整齐,我们可以自定义仿函数让其从大到小排序.
#include <iostream> #include <set> #include <string> using namespace std;class MyCompare { public : bool operator () (int v1, int v2) { return v1 > v2; } }; int main (int argc, char * argv[]) { set<int , MyCompare> var; var.insert (6 ); var.insert (3 ); var.insert (9 ); for (set<int , MyCompare>::iterator it = var.begin (); it != var.end (); it++) cout << *it << endl; system ("pause" ); return 0 ; }
向集合插入自定义类型: 此处使用类做数据存储,插入自定义数据类型时,必须在一开始就指定好排序规则,否则会报错.
#include <iostream> #include <set> #include <string> using namespace std;class Person {public : string m_name; int m_age; public : Person (string name, int age) { this ->m_name = name; this ->m_age = age; } }; class MyCompare { public : bool operator () (const Person & p1, const Person & p2) { if (p1.m_age > p2.m_age) return true ; return false ; } }; int main (int argc, char * argv[]) { set<Person,MyCompare> var; Person p1 ("dawa" , 22 ) ; Person p2 ("xiwa" , 44 ) ; var.insert (p1); var.insert (p2); for (set<Person, MyCompare>::iterator it = var.begin (); it != var.end ();it ++) { cout << "Name: " << (*it).m_name << "Age: " << (*it).m_age << endl; } system ("pause" ); return 0 ; }
Map/Multimap 序列容器 Map映射容器属于关联容器,它的每个键对应着每个值,容器的数据结构同样采用红黑树进行管理,插入的键不允许重复,但值是可以重复的,如果使用Multimap
声明映射容器,则同样可以插入相同的键值.
Map中的所有元素都会根据元素的键值自动排序,所有的元素都是一个Pair同时拥有实值和键值,Pair的第一个元素被视为键值,第二个元素则被视为实值,Map 容器中不允许两个元素有相同的键出现.
通过对组实现键值对: 对组pair<>
是一个键值对的组合,类似于一个字典,每个对组中,包含1个key和1个value.
#include <iostream> #include <set> #include <string> using namespace std;int main (int argc, char * argv[]) { pair<string, int > p (string("lyshark" ), 100 ) ; pair<string, int > p2 = make_pair ("jerry" , 200 ); cout << "Name: " << p.first << endl; cout << "Age: " << p.second << endl; set<int > var; var.insert (10 ); pair<set<int >::iterator, bool > ret = var.insert (10 ); if (!ret.second) cout << "insert error" << endl; system ("pause" ); return 0 ; }
正反向遍历映射容器: 通过使用begin/rbegin,end/rend
等迭代器,实现对MAP映射容器元素的正反向遍历.
#include <iostream> #include <map> #include <string> using namespace std;int main (int argc, char * argv[]) { map<string, int > mp; mp.insert (pair <string, int >("admin0" , 100 )); mp.insert (make_pair ("admin1" , 200 )); mp["admin2" ] = 300 ; mp.erase ("admin2" ); for (map<string, int >::iterator it = mp.begin (); it != mp.end (); it++) cout << "key = " << it->first << " --> value = " << it->second << endl; cout << endl; for (map<string, int >::reverse_iterator it = mp.rbegin (); it != mp.rend ();it ++) cout << "key = " << it->first << " --> value = " << it->second << endl; system ("pause" ); return 0 ; }
查找映射容器中的元素: 首先创建一个映射容器,然后通过迭代器mp.find("admin0");
遍历查找特定的映射元素.
#include <iostream> #include <map> #include <string> using namespace std;int main (int argc, char * argv[]) { map<string, int > mp; mp["admin0" ] = 100 ; mp["admin1" ] = 200 ; mp["admin2" ] = 300 ; map<string, int >::iterator pos = mp.find ("admin0" ); if (pos != mp.end ()) cout << "key = " << pos->first << " --> value = " << pos->second << endl; map<string, int >::iterator ret = mp.lower_bound ("admin0" ); if (ret != mp.end ()) cout << "lower_bound key = " << ret->first << " --> lower_bound value = " << ret->second << endl; map<string, int >::iterator ret1 = mp.upper_bound ("admin0" ); cout << "upper_bound key = " << ret1->first << " --> upper_bound value = " << ret1->second << endl; system ("pause" ); return 0 ; }
遍历映射容器中的结构: 上方代码是查找一个映射元素,本案例将查找一个映射结构,找到后打印出该结构的详细数据.
#include <iostream> #include <map> #include <string> using namespace std;struct StudentInfo { char *name; int year; char *addr; }; struct StudentRecord { int id; StudentInfo stu; }; int main (int argc, char * argv[]) { StudentRecord szArray[] = { { 1 , "admin0" , 22 , "beijing" }, { 2 , "admin1" , 33 , "shanghai" }, { 3 , "admin2" , 24 , "jinan" }, }; map<int , StudentInfo> mp; for (int x = 0 ; x < 3 ; x++) { mp[szArray[x].id] = szArray[x].stu; } map<int , StudentInfo>::iterator start, end; end = mp.end (); for (start = mp.begin (); start != end; start++) cout << "ID: " << (*start).first << " --> Name: " << (*start).second.name << endl; map<int , StudentInfo>::iterator i = mp.find (1 ); cout << "First: " << (*i).first << endl; cout << "Name: " << (*i).second.name << endl; system ("pause" ); return 0 ; }
通过映射容器实现分组: 定义三个不同的部门,然后通过映射容器对其进行分组,并实现遍历并打印出每个分组.
#include <iostream> #include <vector> #include <string> #include <map> using namespace std;enum {RENLI,YANFA,MEISHU}; class Worker { public : string m_name; int m_money; }; void CreateWorker (vector<Worker> &v) { string nameSeed = "ABCDE" ; Worker w; for (int x = 0 ; x < 5 ; x++) { string name; name += nameSeed[x]; int money = rand () % 10000 +10000 ; w.m_name = name; w.m_money = money; v.push_back (w); } } void ShowGroup (multimap<int , Worker> &m) { cout << "Group:" << endl; multimap<int ,Worker>::iterator pos = m.find (RENLI); int index = 0 ; int num = m.count (RENLI); for (; pos != m.end (), index < num; pos++, index++) { cout << "Name: " << pos->second.m_name << endl; } } void SetGroup (vector<Worker> &v,multimap<int ,Worker> & m) { for (vector<Worker>::iterator it = v.begin (); it != v.end (); it++) { int departmentId = rand () % 3 ; m.insert (make_pair (departmentId, *(it))); } } int main (int argc, char * argv[]) { vector<Worker> v; CreateWorker (v); multimap<int , Worker> mp; SetGroup (v,mp); ShowGroup (mp); system ("pause" ); return 0 ; }