文章目錄
3.7 list容器
3.7.1 基本概念
- 不同於連續的線性空間
- 節點中維護下一個節點的內存地址
**功能:**將數據進行鏈式存儲
鏈表(list)是一種物理存儲單元上非連續的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接實現的
鏈表的組成:鏈表由一系列結點組成
結點的組成:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域
STL中的鏈表是一個雙向循環鏈表
- 上圖沒有體現循環。。。
由於鏈表的存儲方式並不是連續的內存空間,因此鏈表list中的迭代器只支持前移和後移,屬於雙向迭代器
list的優點:
- 採用動態存儲分配,不會造成內存浪費和溢出
- 鏈表執行插入和刪除操作十分方便,修改指針即可,不需要移動大量元素
list的缺點:
- 鏈表靈活,但是空間(指針域) 和 時間(遍歷)額外耗費較大
List插入操作和刪除操作都不會造成原有list迭代器的失效,這在vector是不成立的(因爲vector可能擴容,從而改變元素的位置,導致指針失效)
3.7.2 構造函數
功能描述:
- 創建list容器
函數原型:
list<T> lst;
//list採用採用模板類實現,對象的默認構造形式:list(beg,end);
//構造函數將[beg, end)區間中的元素拷貝給本身。list(n,elem);
//構造函數將n個elem拷貝給本身。list(const list &lst);
//拷貝構造函數。
示例:
#include <list>
void printList(const list<int>& L) {
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
void test01()
{
list<int>L1; //默認構造
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
printList(L1);
//區間方式構造
list<int>L2(L1.begin(),L1.end());
printList(L2);
//拷貝構造
list<int>L3(L2);
printList(L3);
list<int>L4(10, 1000);
printList(L4);
}
int main() {
test01();
system("pause");
return 0;
}
- 總結:list構造方式同其他STL常用容器
3.7.3 賦值和交換
功能描述:
- 給list容器進行賦值,以及交換list容器
函數原型:
assign(beg, end);
//將[beg, end)區間中的數據拷貝賦值給本身。assign(n, elem);
//將n個elem拷貝賦值給本身。list& operator=(const list &lst);
//重載等號操作符swap(lst);
//將lst與本身的元素互換。
示例:
#include <list>
void printList(const list<int>& L) {
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
//賦值和交換
void test01()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
printList(L1);
//賦值
list<int>L2;
L2 = L1; //operator= 賦值
printList(L2);
list<int>L3;
L3.assign(L2.begin(), L2.end());
printList(L3);
list<int>L4;
L4.assign(10, 100);
printList(L4);
}
//交換
void test02()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
list<int>L2;
L2.assign(10, 100);
cout << "交換前: " << endl;
printList(L1);
printList(L2);
cout << endl;
L1.swap(L2);
cout << "交換後: " << endl;
printList(L1);
printList(L2);
}
int main() {
//test01();
test02();
system("pause");
return 0;
}
3.7.4 大小操作
功能描述:
- 對list容器的大小進行操作
函數原型:
-
size();
//返回容器中元素的個數 -
empty();
//判斷容器是否爲空 -
resize(num);
//重新指定容器的長度爲num,若容器變長,則以默認值填充新位置。 //如果容器變短,則末尾超出容器長度的元素被刪除。
-
resize(num, elem);
//重新指定容器的長度爲num,若容器變長,則以elem值填充新位置。 //如果容器變短,則末尾超出容器長度的元素被刪除。
示例:
#include <list>
void printList(const list<int>& L) {
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
//大小操作
void test01()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
if (L1.empty())
{
cout << "L1爲空" << endl;
}
else
{
cout << "L1不爲空" << endl;
cout << "L1的大小爲: " << L1.size() << endl;
}
//重新指定大小
L1.resize(10);
printList(L1);
L1.resize(2);
printList(L1);
}
int main() {
test01();
system("pause");
return 0;
}
總結:
- 判斷是否爲空 — empty
- 返回元素個數 — size
- 重新指定個數 — resize
3.7.5 插入和刪除
功能描述:
- 對list容器進行數據的插入和刪除
函數原型:
- push_back(elem);//在容器尾部加入一個元素
- pop_back();//刪除容器中最後一個元素
- push_front(elem);//在容器開頭插入一個元素
- pop_front();//從容器開頭移除第一個元素
- insert(pos,elem);//在pos位置插elem元素的拷貝,返回新數據的位置。
- insert(pos,n,elem);//在pos位置插入n個elem數據,無返回值。
- insert(pos,beg,end);//在pos位置插入[beg,end)區間的數據,無返回值。
- clear();//移除容器的所有數據
- erase(beg,end);//刪除[beg,end)區間的數據,返回下一個數據的位置。
- erase(pos);//刪除pos位置的數據,返回下一個數據的位置。
- remove(elem);//刪除容器中所有與elem值相等的元素。
示例:
#include <list>
void printList(const list<int>& L) {
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
//插入和刪除
void test01()
{
list<int> L;
//尾插
L.push_back(10);
L.push_back(20);
L.push_back(30);
//頭插
L.push_front(100);
L.push_front(200);
L.push_front(300);
printList(L);
//尾刪
L.pop_back();
printList(L);
//頭刪
L.pop_front();
printList(L);
//插入
list<int>::iterator it = L.begin();
L.insert(++it, 1000); //第一個位置後插入,不是頭插,偏移了一次
printList(L);
//刪除
it = L.begin();
L.erase(++it);
printList(L);
//移除
L.push_back(10000);
L.push_back(10000);
L.push_back(10000);
printList(L);
L.remove(10000);
printList(L);
//清空
L.clear();
printList(L);
}
int main() {
test01();
system("pause");
return 0;
}
總結:
- 尾插 — push_back
- 尾刪 — pop_back
- 頭插 — push_front
- 頭刪 — pop_front
- 插入 — insert
- 刪除 — erase
- 移除 — remove
- 清空 — clear
- 迭代器可移動
3.7.6 數據存取
功能描述:
- 對list容器中數據進行存取
函數原型:
front();
//返回第一個元素。back();
//返回最後一個元素。
示例:
#include <list>
//數據存取
void test01()
{
list<int>L1;
L1.push_back(10);
L1.push_back(20);
L1.push_back(30);
L1.push_back(40);
//cout << L1.at(0) << endl;//錯誤 不支持at訪問數據
//cout << L1[0] << endl; //錯誤 不支持[]方式訪問數據
cout << "第一個元素爲: " << L1.front() << endl;
cout << "最後一個元素爲: " << L1.back() << endl;
//list容器的迭代器是雙向迭代器,不支持隨機訪問
list<int>::iterator it = L1.begin();
//it = it + 1; 錯誤,因爲不可以跳躍訪問,即使是+1,類比始作俑者的邏輯
//但是若干次it++,it--可以
}
int main() {
test01();
system("pause");
return 0;
}
總結:
- list容器中不可以通過[]或者at方式訪問數據
- 返回第一個元素 — front
- 返回最後一個元素 — back
- it++:說明可以向後訪問,it–同理
- it =it +1不報錯,說明支持隨機訪問,類比始作俑者的邏輯
3.7.7 反轉和排序
功能描述:
- 將容器中的元素反轉,以及將容器中的數據進行排序
函數原型:
reverse();
//反轉鏈表sort();
//鏈表排序
示例:
void printList(const list<int>& L) {
for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
//降序
bool myCompare(int val1 , int val2)
{
return val1 > val2;
}
//反轉和排序
void test01()
{
list<int> L;
L.push_back(90);
L.push_back(30);
L.push_back(20);
L.push_back(70);
printList(L);
//反轉容器的元素
L.reverse();
printList(L);
//排序
L.sort(); //默認的排序規則 從小到大
printList(L);
L.sort(myCompare); //指定規則,從大到小
printList(L);
}
int main() {
test01();
system("pause");
return 0;
}
總結:
- 反轉 — reverse
- 排序 — sort (成員函數)
3.7.8 排序案例
案例描述:將Person自定義數據類型進行排序,Person中屬性有姓名、年齡、身高
排序規則:按照年齡進行升序,如果年齡相同按照身高進行降序
示例:
#include <list>
#include <string>
class Person {
public:
Person(string name, int age , int height) {
m_Name = name;
m_Age = age;
m_Height = height;
}
public:
string m_Name; //姓名
int m_Age; //年齡
int m_Height; //身高
};
//指定排序規則
bool ComparePerson(Person& p1, Person& p2) {
//年齡相同,按身高降序
if (p1.m_Age == p2.m_Age) {
return p1.m_Height > p2.m_Height;
}
else
{ //按年齡升序
return p1.m_Age < p2.m_Age;
}
}
void test01() {
list<Person> L;
Person p1("劉備", 35 , 175);
Person p2("曹操", 45 , 180);
Person p3("孫權", 40 , 170);
Person p4("趙雲", 25 , 190);
Person p5("張飛", 35 , 160);
Person p6("關羽", 35 , 200);
L.push_back(p1);
L.push_back(p2);
L.push_back(p3);
L.push_back(p4);
L.push_back(p5);
L.push_back(p6);
for (list<Person>::iterator it = L.begin(); it != L.end(); it++) {
cout << "姓名: " << it->m_Name << " 年齡: " << it->m_Age
<< " 身高: " << it->m_Height << endl;
}
cout << "---------------------------------" << endl;
L.sort(ComparePerson); //排序
for (list<Person>::iterator it = L.begin(); it != L.end(); it++) {
cout << "姓名: " << it->m_Name << " 年齡: " << it->m_Age
<< " 身高: " << it->m_Height << endl;
}
}
int main() {
test01();
system("pause");
return 0;
}
總結:
-
對於自定義數據類型,必須要指定排序規則,否則編譯器不知道如何進行排序
-
高級排序只是在排序規則上再進行一次邏輯規則制定,並不複雜
3.8 set/ multiset 容器
3.8.1 基本概念
簡介:
- 所有元素都會在插入時自動被排序
本質:
- set/multiset屬於關聯式容器,底層結構是用二叉樹實現。
set和multiset區別:
- set不允許容器中有重複的元素
- multiset允許容器中有重複的元素
3.8.2 構造和賦值
功能描述:創建set容器以及賦值
構造:
set<T> st;
//默認構造函數:set(const set &st);
//拷貝構造函數
賦值:
set& operator=(const set &st);
//重載等號操作符
示例:
#include <set>
void printSet(set<int> & s)
{
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//構造和賦值
void test01()
{
set<int> s1;
//插入數據只有insert方式
s1.insert(10);
s1.insert(30);
s1.insert(20);
s1.insert(40);
printSet(s1);
//拷貝構造
set<int>s2(s1);
printSet(s2);
//賦值
set<int>s3;
s3 = s2;
printSet(s3);
}
int main() {
test01();
system("pause");
return 0;
}
總結:
- set容器插入數據時用insert
- set容器插入數據的數據會自動排序
3.8.3 大小和交換
功能描述:
- 統計set容器大小以及交換set容器
函數原型:
size();
//返回容器中元素的數目empty();
//判斷容器是否爲空swap(st);
//交換兩個容器
示例:
#include <set>
void printSet(set<int> & s)
{
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//大小
void test01()
{
set<int> s1;
s1.insert(10);
s1.insert(30);
s1.insert(20);
s1.insert(40);
if (s1.empty())
{
cout << "s1爲空" << endl;
}
else
{
cout << "s1不爲空" << endl;
cout << "s1的大小爲: " << s1.size() << endl;
}
}
//交換
void test02()
{
set<int> s1;
s1.insert(10);
s1.insert(30);
s1.insert(20);
s1.insert(40);
set<int> s2;
s2.insert(100);
s2.insert(300);
s2.insert(200);
s2.insert(400);
cout << "交換前" << endl;
printSet(s1);
printSet(s2);
cout << endl;
cout << "交換後" << endl;
s1.swap(s2);
printSet(s1);
printSet(s2);
}
int main() {
//test01();
test02();
system("pause");
return 0;
}
總結:
- 統計大小 — size
- 判斷是否爲空 — empty
- 交換容器 — swap
- 不支持resize方法
3.8.4 插入和刪除
功能描述:
- set容器進行插入數據和刪除數據
函數原型:
insert(elem);
//在容器中插入元素。clear();
//清除所有元素erase(pos);
//刪除pos迭代器所指的元素,返回下一個元素的迭代器。erase(beg, end);
//刪除區間[beg,end)的所有元素 ,返回下一個元素的迭代器。erase(elem);
//刪除容器中值爲elem的元素。
示例:
#include <set>
void printSet(set<int> & s)
{
for (set<int>::iterator it = s.begin(); it != s.end(); it++)
{
cout << *it << " ";
}
cout << endl;
}
//插入和刪除
void test01()
{
set<int> s1;
//插入
s1.insert(10);
s1.insert(30);
s1.insert(20);
s1.insert(40);
printSet(s1);
//刪除
s1.erase(s1.begin());
printSet(s1);
s1.erase(30);
printSet(s1);
//清空
//s1.erase(s1.begin(), s1.end());
s1.clear();
printSet(s1);
}
int main() {
test01();
system("pause");
return 0;
}
總結:
- 插入 — insert
- 刪除 — erase
- 清空 — clear
3.8.5 查找和統計
功能描述:
- 對set容器進行查找數據以及統計數據
函數原型:
find(key);
//查找key是否存在,若存在,返回該鍵的元素的迭代器;若不存在,返回set.end();count(key);
//統計key的元素個數
示例:
#include <set>
//查找和統計
void test01()
{
set<int> s1;
//插入
s1.insert(10);
s1.insert(30);
s1.insert(20);
s1.insert(40);
//查找
set<int>::iterator pos = s1.find(30);
if (pos != s1.end())
{
cout << "找到了元素 : " << *pos << endl;
}
else
{
cout << "未找到元素" << endl;
}
//統計
int num = s1.count(30);
cout << "num = " << num << endl;
}
int main() {
test01();
system("pause");
return 0;
}
總結:
- 查找 — find (返回的是迭代器)
- 統計 — count (對於set,結果爲0或者1)
3.8.6 set和multiset區別
學習目標:
- 掌握set和multiset的區別
區別:
- set不可以插入重複數據,而multiset可以
- set插入數據的同時會返回插入結果,表示插入是否成功
- multiset不會檢測數據,因此可以插入重複數據
- 上圖爲底層,_Pairib爲set的insert方法的返回值,從pair的組成可見可通過pair.second = bool來判斷是否插入成功
- pair.first返回的是迭代器,即插入的位置
pair<set<int>::iterator, bool> ret = s.insert(10);
if (ret.second) {
cout << "第二次插入成功!" << endl;
}
else {
cout << "第二次插入失敗!" << endl;
}
示例:
#include <set>
//set和multiset區別
void test01()
{
set<int> s;
pair<set<int>::iterator, bool> ret = s.insert(10); //插入位置——插入成功否
if (ret.second) {
cout << "第一次插入成功!" << endl;
}
else {
cout << "第一次插入失敗!" << endl;
}
ret = s.insert(10);
if (ret.second) {
cout << "第二次插入成功!" << endl;
}
else {
cout << "第二次插入失敗!" << endl;
}
//multiset
multiset<int> ms;
ms.insert(10); //返回迭代器,即插入的位置
ms.insert(10);
for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
int main() {
test01();
system("pause");
return 0;
}
總結:
- 如果不允許插入重複數據可以利用set
- 如果需要插入重複數據利用multiset
3.8.7 pair對組創建
功能描述:
- 成對出現的數據,利用對組可以返回兩個數據
兩種創建方式:
pair<type, type> p ( value1, value2 );
pair<type, type> p = make_pair( value1, value2 );
示例:
#include <string>
//對組創建
void test01()
{
//不需要頭文件
pair<string, int> p(string("Tom"), 20);
cout << "姓名: " << p.first << " 年齡: " << p.second << endl;
pair<string, int> p2 = make_pair("Jerry", 10);
cout << "姓名: " << p2.first << " 年齡: " << p2.second << endl;
}
int main() {
test01();
system("pause");
return 0;
}
3.8.8 set容器排序
學習目標:
- set容器默認排序規則爲從小到大,掌握如何改變排序規則
主要技術點:
- 利用仿函數(本質是類),可以改變排序規則
示例一 set存放內置數據類型
#include <set>
class MyCompare
{
public:
bool operator()(int v1, int v2) {
return v1 > v2;
}
};
void test01()
{
set<int> s1;
s1.insert(10);
s1.insert(40);
s1.insert(20);
s1.insert(30);
s1.insert(50);
//默認從小到大
for (set<int>::iterator it = s1.begin(); it != s1.end(); it++) {
cout << *it << " ";
}
cout << endl;
//插入前指定排序規則
set<int,MyCompare> s2;
s2.insert(10);
s2.insert(40);
s2.insert(20);
s2.insert(30);
s2.insert(50);
for (set<int, MyCompare>::iterator it = s2.begin(); it != s2.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
int main() {
test01();
system("pause");
return 0;
}
總結:利用仿函數可以指定set容器的排序規則
示例二 set存放自定義數據類型
#include <set>
#include <string>
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
class comparePerson
{
public:
bool operator()(const Person& p1, const Person &p2)
{
//按照年齡進行排序 降序
return p1.m_Age > p2.m_Age;
}
};
void test01()
{
set<Person, comparePerson> s;
Person p1("劉備", 23);
Person p2("關羽", 27);
Person p3("張飛", 25);
Person p4("趙雲", 21);
s.insert(p1);
s.insert(p2);
s.insert(p3);
s.insert(p4);
for (set<Person, comparePerson>::iterator it = s.begin(); it != s.end(); it++)
{
cout << "姓名: " << it->m_Name << " 年齡: " << it->m_Age << endl;
}
}
int main() {
test01();
system("pause");
return 0;
}
- 總結:對於自定義數據類型,set必須指定排序規則纔可以插入數據
3.9 map/ multimap容器
3.9.1 map基本概念
簡介:
- map中所有元素都是pair
- pair中第一個元素爲key(鍵值),起到索引作用,第二個元素爲value(實值)
- 所有元素都會根據元素的鍵值自動排序
本質:
- map/multimap屬於關聯式容器,底層結構是用二叉樹實現。
優點:
- 可以根據key值快速找到value值
map和multimap區別:
- map不允許容器中有重複key值元素
- multimap允許容器中有重複key值元素
3.9.2 構造和賦值
功能描述:
- 對map容器進行構造和賦值操作
函數原型:
構造:
map<T1, T2> mp;
//map默認構造函數:map(const map &mp);
//拷貝構造函數
賦值:
map& operator=(const map &mp);
//重載等號操作符
示例:
#include <map>
void printMap(map<int,int>&m)
{
for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
{
cout << "key = " << it->first << " value = " << it->second << endl;
}
cout << endl;
}
void test01()
{
map<int,int>m; //默認構造
m.insert(pair<int, int>(1, 10)); //匿名對組
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(3, 30));
printMap(m);
map<int, int>m2(m); //拷貝構造
printMap(m2);
map<int, int>m3;
m3 = m2; //賦值
printMap(m3);
}
int main() {
test01();
system("pause");
return 0;
}
總結:map中所有元素都是成對出現,插入數據時候要使用對組
3.9.3 大小和交換
功能描述:
- 統計map容器大小以及交換map容器
函數原型:
size();
//返回容器中元素的數目empty();
//判斷容器是否爲空swap(st);
//交換兩個集合容器
示例:
#include <map>
void printMap(map<int,int>&m)
{
for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
{
cout << "key = " << it->first << " value = " << it->second << endl;
}
cout << endl;
}
void test01()
{
map<int, int>m;
m.insert(pair<int, int>(1, 10));
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(3, 30));
if (m.empty())
{
cout << "m爲空" << endl;
}
else
{
cout << "m不爲空" << endl;
cout << "m的大小爲: " << m.size() << endl;
}
}
//交換
void test02()
{
map<int, int>m;
m.insert(pair<int, int>(1, 10));
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(3, 30));
map<int, int>m2;
m2.insert(pair<int, int>(4, 100));
m2.insert(pair<int, int>(5, 200));
m2.insert(pair<int, int>(6, 300));
cout << "交換前" << endl;
printMap(m);
printMap(m2);
cout << "交換後" << endl;
m.swap(m2);
printMap(m);
printMap(m2);
}
int main() {
test01();
test02();
system("pause");
return 0;
}
總結:
- 統計大小 — size
- 判斷是否爲空 — empty
- 交換容器 — swap
3.9.4 插入和刪除
功能描述:
- map容器進行插入數據和刪除數據
函數原型:
insert(elem);
//在容器中插入元素。clear();
//清除所有元素erase(pos);
//刪除pos迭代器所指的元素,返回下一個元素的迭代器。erase(beg, end);
//刪除區間[beg,end)的所有元素 ,返回下一個元素的迭代器。erase(key);
//刪除容器中值爲key的元素。
示例:
#include <map>
void printMap(map<int,int>&m)
{
for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
{
cout << "key = " << it->first << " value = " << it->second << endl;
}
cout << endl;
}
void test01()
{
//插入
map<int, int> m;
//第一種插入方式
m.insert(pair<int, int>(1, 10));
//第二種插入方式
m.insert(make_pair(2, 20));
//第三種插入方式
m.insert(map<int, int>::value_type(3, 30));
//第四種插入方式
m[4] = 40;
printMap(m);
//刪除
m.erase(m.begin());
printMap(m);
m.erase(3); //按key刪除
printMap(m);
//清空
m.erase(m.begin(),m.end());
m.clear();
printMap(m);
}
int main() {
test01();
system("pause");
return 0;
}
總結:
- map插入方式很多,記住其一即可
- 插入 — insert
- 刪除 — erase
- 清空 — clear
- 如上圖所示,明明是想查看m[5]的值,但map中沒有,此時會自動創建(5,0)的鍵值對,不符合預期邏輯
3.9.5 查找和統計
功能描述:
- 對map容器進行查找數據以及統計數據
函數原型:
find(key);
//查找key是否存在,若存在,返回該鍵的元素的迭代器;若不存在,返回set.end();count(key);
//統計key的元素個數
示例:
#include <map>
//查找和統計
void test01()
{
map<int, int>m;
m.insert(pair<int, int>(1, 10));
m.insert(pair<int, int>(2, 20));
m.insert(pair<int, int>(3, 30));
//查找
map<int, int>::iterator pos = m.find(3);
if (pos != m.end())
{
cout << "找到了元素 key = " << (*pos).first << " value = " << (*pos).second << endl;
}
else
{
cout << "未找到元素" << endl;
}
//統計
int num = m.count(3);
cout << "num = " << num << endl;
}
int main() {
test01();
system("pause");
return 0;
}
總結:
-
查找 — find (返回的是迭代器)
-
統計 — count (對於map,結果爲0或者1)
-
先進去的對組會讓後進去的對組插入不到map中(注意不是覆蓋)
3.9.6 map容器排序
學習目標:
- map容器默認排序規則爲 按照key值進行 從小到大排序,掌握如何改變排序規則
主要技術點:
- 利用仿函數,可以改變排序規則
示例:
#include <map>
class MyCompare {
public:
bool operator()(int v1, int v2) {
return v1 > v2;
}
};
void test01()
{
//默認從小到大排序
//利用仿函數實現從大到小排序
map<int, int, MyCompare> m;
m.insert(make_pair(1, 10));
m.insert(make_pair(2, 20));
m.insert(make_pair(3, 30));
m.insert(make_pair(4, 40));
m.insert(make_pair(5, 50));
for (map<int, int, MyCompare>::iterator it = m.begin(); it != m.end(); it++) {
cout << "key:" << it->first << " value:" << it->second << endl;
}
}
int main() {
test01();
system("pause");
return 0;
}
總結:
- 利用仿函數可以指定map容器的排序規則
- 對於自定義數據類型,map必須要指定排序規則,同set容器
3.10 案例-員工分組
3.10.1 案例描述
- 公司今天招聘了10個員工(ABCDEFGHIJ),10名員工進入公司之後,需要指派員工在那個部門工作
- 員工信息有: 姓名 工資組成;部門分爲:策劃、美術、研發
- 隨機給10名員工分配部門和工資
- 通過multimap進行信息的插入 key(部門編號) value(員工)
- 分部門顯示員工信息
3.10.2 實現步驟
- 創建10名員工,放到vector中
- 遍歷vector容器,取出每個員工,進行隨機分組
- 分組後,將員工部門編號作爲key,具體員工作爲value,放入到multimap容器中
- 分部門顯示員工信息
案例代碼:
#include<iostream>
using namespace std;
#include <vector>
#include <string>
#include <map>
#include <ctime>
/*
- 公司今天招聘了10個員工(ABCDEFGHIJ),10名員工進入公司之後,需要指派員工在那個部門工作
- 員工信息有: 姓名 工資組成;部門分爲:策劃、美術、研發
- 隨機給10名員工分配部門和工資
- 通過multimap進行信息的插入 key(部門編號) value(員工)
- 分部門顯示員工信息
*/
#define CEHUA 0
#define MEISHU 1
#define YANFA 2
class Worker
{
public:
string m_Name;
int m_Salary;
};
void createWorker(vector<Worker>&v)
{
string nameSeed = "ABCDEFGHIJ";
for (int i = 0; i < 10; i++)
{
Worker worker;
worker.m_Name = "員工";
worker.m_Name += nameSeed[i];
worker.m_Salary = rand() % 10000 + 10000; // 10000 ~ 19999
//將員工放入到容器中
v.push_back(worker);
}
}
//員工分組
void setGroup(vector<Worker>&v,multimap<int,Worker>&m)
{
for (vector<Worker>::iterator it = v.begin(); it != v.end(); it++)
{
//產生隨機部門編號
int deptId = rand() % 3; // 0 1 2
//將員工插入到分組中
//key部門編號,value具體員工
m.insert(make_pair(deptId, *it));
}
}
void showWorkerByGourp(multimap<int,Worker>&m)
{
// 0 A B C 1 D E 2 F G ...
cout << "策劃部門:" << endl;
multimap<int,Worker>::iterator pos = m.find(CEHUA);
int count = m.count(CEHUA); // 統計具體人數
int index = 0;
for (; pos != m.end() && index < count; pos++ , index++)
{
cout << "姓名: " << pos->second.m_Name << " 工資: " << pos->second.m_Salary << endl;
}
cout << "----------------------" << endl;
cout << "美術部門: " << endl;
pos = m.find(MEISHU);
count = m.count(MEISHU); // 統計具體人數
index = 0;
for (; pos != m.end() && index < count; pos++, index++)
{
cout << "姓名: " << pos->second.m_Name << " 工資: " << pos->second.m_Salary << endl;
}
cout << "----------------------" << endl;
cout << "研發部門: " << endl;
pos = m.find(YANFA);
count = m.count(YANFA); // 統計具體人數
index = 0;
for (; pos != m.end() && index < count; pos++, index++)
{
cout << "姓名: " << pos->second.m_Name << " 工資: " << pos->second.m_Salary << endl;
}
}
int main() {
srand((unsigned int)time(NULL));
//1、創建員工
vector<Worker>vWorker;
createWorker(vWorker);
//2、員工分組
multimap<int, Worker>mWorker;
setGroup(vWorker, mWorker);
//3、分組顯示員工
showWorkerByGourp(mWorker);
////測試
//for (vector<Worker>::iterator it = vWorker.begin(); it != vWorker.end(); it++)
//{
// cout << "姓名: " << it->m_Name << " 工資: " << it->m_Salary << endl;
//}
system("pause");
return 0;
}
總結:
- 當數據以鍵值對形式存在,可以考慮用map 或 multimap