網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
正文
一個(gè)地圖由鍵/值對(duì)組成。每一對(duì)都是一個(gè)元素。一個(gè)地圖中的所有鍵都是唯一的。一個(gè)地圖可以按鍵進(jìn)行排序。排序可以是升序或降序。升序是默認(rèn)的。地圖中的排序并不總是直接的。它需要一個(gè)比較函數(shù)對(duì)象。如果比較對(duì)象被忽略了,就會(huì)發(fā)生默認(rèn)的排序。
如果鍵是恒定的指向字符的指針,地圖就會(huì)按鍵的指針排序,而不是按鍵的字符串字?jǐn)?shù)排序。這幾乎不是任何人想要的。考慮以下水果的鍵/值對(duì)和它們的外部顏色。
"plum" => "purple"
"blackberry" => "dark blue-black"
"watermelon" => "green"
"apricot", => "orange"
"papaya" => "orange"
"banana" => "yellow"
水果是鍵,而顏色是值。這個(gè)元素列表(鍵/值對(duì))是沒(méi)有排序的。下面的程序創(chuàng)建了這個(gè)列表的映射,并按原樣顯示,沒(méi)有按字符串字面排序。
#include <iostream>
#include <map>
using namespace std;
int main()
{
map<const char*, const char*> mp;
mp["plum"] = "purple";
mp["blackberry"] = "dark blue-black";
mp["watermelon"] = "green";
mp["apricot"] = "orange";
mp["papaya"] = "orange";
mp["banana"] = "yellow";
for (map<const char*, const char*>::iterator it = mp.begin(); it != mp.end(); it++)
cout << it->first << " => " << it->second << endl;
return 0;
}
輸出結(jié)果是:
?plum => purple
? ? blackberry => dark blue-black
? ? watermelon => green
? ? apricot => orange
? ? papaya => orange
? ? banana => yellow
未按字符串字面排序,但按指針排序。要在C++程序中使用地圖,必須用include指令來(lái)包含地圖庫(kù)。
創(chuàng)建上述簡(jiǎn)單地圖的另一種方法是如下。
#include <iostream>
#include <map>
using namespace std;
int main()
{
map<const char*, const char*> mp({{"plum","purple"}, {"blackberry","dark blue-black"}, {"watermelon","green"}, {"apricot","orange"}, {"papaya","orange"}, {"banana","yellow"}});
for (map<const char*, const char*>::iterator it = mp.begin(); it != mp.end(); it++)
cout << it->first << " => " << it->second << endl;
return 0;
}
輸出結(jié)果是:
?plum => purple
? ? blackberry => dark blue-black
? ? watermelon => green
? ? apricot => orange
? ? papaya => orange
? ? banana => yellow
未按字符串字面排序,但按指針排序。如果鍵值是整數(shù),輸出將按鍵值排序。在實(shí)踐中,許多地圖的鍵是字符串字面。這篇文章解釋了字符串字面的鍵是如何對(duì)地圖進(jìn)行排序的。
創(chuàng)建過(guò)程中的排序
構(gòu)建地圖的完整模板是:
template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>> class map;
類(lèi),Compare和Allocator,有默認(rèn)值。也就是說(shuō),它們有默認(rèn)的專(zhuān)業(yè)化,不必在map聲明(實(shí)例化)中進(jìn)行類(lèi)型化。這里要關(guān)注的是比較類(lèi)。這個(gè)類(lèi)的名字是Compare,默認(rèn)的特殊化是 "less"。"less<Key "意味著按升序排序。另一個(gè)選項(xiàng)是 "greater",意思是降序排序。
一個(gè)地圖在創(chuàng)建時(shí)通常是按鍵值排序的。如果鍵是const char*,那么指向引號(hào)字面字符串的指針將被排序,而不是字面文本。要在創(chuàng)建過(guò)程中把字符串作為鍵進(jìn)行排序,字符串必須是由字符串類(lèi)實(shí)例化的字符串對(duì)象的字面意思。這意味著必須包括字符串庫(kù)和地圖庫(kù)。
創(chuàng)建升序
在下面的程序中,地圖被創(chuàng)建,升序排序。
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
map<string, const char*, less<string>> mp;
mp["plum"] = "purple";
mp["blackberry"] = "dark blue-black";
mp["watermelon"] = "green";
mp["apricot"] = "orange";
mp["papaya"] = "orange";
mp["banana"] = "yellow";
for (map<string, const char*>::iterator it = mp.begin(); it != mp.end(); it++)
cout << it->first << " => " << it->second << endl;
return 0;
}
輸出結(jié)果是:
apricot => orange
? ? banana => yellow
? ? blackberry => dark blue-black
? ? papaya => orange
? ? plum => purple
? ? watermelon => green
即使模板中省略了less,排序仍然會(huì)是升序的,因?yàn)閘ess是默認(rèn)的。
創(chuàng)建降序
為了創(chuàng)建一個(gè)地圖,使其按鍵的降序排序,必須對(duì)比較專(zhuān)業(yè)化進(jìn)行編碼。下面的程序說(shuō)明了這一點(diǎn)。
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
map<string, const char*, greater<string>> mp;
mp["plum"] = "purple";
mp["blackberry"] = "dark blue-black";
mp["watermelon"] = "green";
mp["apricot"] = "orange";
mp["papaya"] = "orange";
mp["banana"] = "yellow";
for (map<string, const char*>::iterator it = mp.begin(); it != mp.end(); it++)
cout << it->first << " => " << it->second << endl;
return 0;
}
輸出結(jié)果是:
?watermelon => green
? ? plum => purple
? ? papaya => orange
? ? blackberry => dark blue-black
? ? banana => yellow
? ? apricot => orange
生成一個(gè)范圍的降序
一個(gè)地圖的范圍可以按降序產(chǎn)生。這涉及到創(chuàng)建第二個(gè)地圖,它是第一個(gè)地圖的一個(gè)范圍。下面的程序說(shuō)明了這一點(diǎn)。
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
map<string, const char*> mp;
mp["plum"] = "purple";
mp["blackberry"] = "dark blue-black";
mp["watermelon"] = "green";
mp["apricot"] = "orange";
mp["papaya"] = "orange";
mp["banana"] = "yellow";
map<string, const char*>::iterator itB = mp.begin();
itB++;
map<string, const char*>::iterator itE = mp.end();
itE--;
map<string, const char*, greater<string>> mpR(itB, itE);
for (map<string, const char*>::iterator it = mpR.begin(); it != mpR.end(); it++)
cout << it->first << " => " << it->second << endl;
return 0;
}
輸出結(jié)果是:
?plum => purple
? ? papaya => orange
? ? blackberry => dark blue-black
? ? banana => yellow
第一個(gè)地圖對(duì)象有六個(gè)元素,分別是
apricot => orange
banana => yellow
blackberry => dark blue-black
papaya => orange
plum => purple
watermelon => green
考慮的范圍是:
banana => yellow
blackberry => dark blue-black
papaya => orange
plum => purple
watermelon => green
在代碼中,"itB++"指向{"香蕉","黃色"},"itE-"指向{"西瓜","綠色"}的范圍。在C++中處理一個(gè)范圍時(shí),最后一個(gè)元素不參與操作。于是,輸出有四個(gè)元素,{"西瓜","綠"}被省略了。
第二個(gè)map的Compare模板參數(shù)的特化是 greater。如果它是less或者省略,那么這個(gè)范圍會(huì)導(dǎo)致升序。
通過(guò)鍵比較兩個(gè)元素
key_compare key_comp() const
這個(gè)成員函數(shù)返回map容器用來(lái)比較鍵的比較對(duì)象的副本。比較對(duì)象是一個(gè)函數(shù)對(duì)象。它將把兩個(gè)鍵作為參數(shù),如果左鍵小于右鍵,則返回真。有了這個(gè),代碼段應(yīng)該是。
key_compare kc = mp.key_comp();
bool bl = kc("watermelon", "apricot");
key_compare不被編譯器識(shí)別。在這個(gè)代碼段中消除key_compare,在第二條語(yǔ)句中替換掉kc,結(jié)果是。
bool bl = mp.key_comp()("watermelon", "apricot");
下面的程序說(shuō)明了key_comp()的使用。
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
map<string, const char*> mp;
mp["plum"] = "purple";
mp["blackberry"] = "dark blue-black";
mp["watermelon"] = "green";
mp["apricot"] = "orange";
mp["papaya"] = "orange";
mp["banana"] = "yellow";
bool bl = mp.key_comp()("watermelon", "apricot");
cout << bl << endl;
return 0;
}
輸出結(jié)果是0,表示錯(cuò)誤。
上述代碼段的真正問(wèn)題是,key_compare的命名空間沒(méi)有得到很好的表達(dá)。如果這段代碼是
map<string, const char*>::key_compare kc = mp.key_comp();
bool bl = kc("watermelon", "apricot");
它本來(lái)可以工作(被編譯器接受)。
value_compare value_comp() const
這個(gè)成員函數(shù)與key_comp()類(lèi)似。注意:這里指的不是鍵/值對(duì)的值,而是鍵/值對(duì)的元素。所以,value_compare函數(shù)對(duì)象的兩個(gè)參數(shù)是迭代器元素。下面的程序使用value_comp(),在比較第一個(gè)和最后一個(gè)元素,{"杏","橙"}和{"西瓜","綠"}:
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
map<string, const char*, less<string>> mp;
mp["plum"] = "purple";
mp["blackberry"] = "dark blue-black";
mp["watermelon"] = "green";
mp["apricot"] = "orange";
mp["papaya"] = "orange";
mp["banana"] = "yellow";
map<string, const char*>::iterator itB = mp.begin();
map<string, const char*>::iterator itE = mp.end();
itE--;
map<string, const char*>::value_compare vc = mp.value_comp();
bool bl = vc(*itB, *itE);
cout << bl << endl;
return 0;
}
輸出是1,表示真。迭代器itB和itE被解讀為有它們的元素,用的是嵌套運(yùn)算符。
對(duì)用初始化器列表創(chuàng)建的地圖進(jìn)行排序
在下面的程序中,排序是降序的,鍵是字符串對(duì)象,從字符串類(lèi)實(shí)例化出來(lái)。
#include <iostream>
#include <string>
#include <map>
using namespace std;
int main()
{
map<string, const char*, greater<string>> mp({{"plum","purple"}, {"blackberry","dark blue-black"}, {"watermelon","green"}, {"apricot","orange"}, {"papaya","orange"}, {"banana","yellow"}});
for (map<string, const char*>::iterator it = mp.begin(); it != mp.end(); it++)
cout << it->first << " => " << it->second << endl;
return 0;
}
輸出結(jié)果是。
? ? watermelon => green
? ? plum => purple
? ? papaya => orange
? ? blackberry => dark blue-black
? ? banana => yellow
? ? apricot => orange
結(jié)論
一個(gè)地圖的創(chuàng)建是按照鍵來(lái)排序的,升序。升序是默認(rèn)的順序。要想讓它降序,請(qǐng)?jiān)谀0鍏?shù)列表中加入模板參數(shù)的特殊化,即作為第三個(gè)參數(shù)的大號(hào)。注意:如果鍵值是字符串,它們必須從字符串類(lèi)中實(shí)例化出來(lái),如上圖所示。作為const-char*或char-arr[]的字符串鍵,其指針最終會(huì)被排序,而不是其字面意義。
原文鏈接:https://juejin.cn/post/7122325544095449125
相關(guān)推薦
- 2022-09-22 描述Servlet生命周期,Servlet是線程安全的嗎? 為什么?
- 2023-01-20 python-try-except:pass的用法及說(shuō)明_python
- 2022-04-27 Numpy的各種下標(biāo)操作的示例代碼_python
- 2025-02-10 window11 系統(tǒng)安裝 yarn
- 2022-08-18 Git多人協(xié)同開(kāi)發(fā)緊急修復(fù)線上bug操作指南_相關(guān)技巧
- 2022-04-17 mac 使用zsh vscode和終端node默認(rèn)版本不一致 (nvm node版本管理工具)
- 2022-06-06 uniApp、API ‘offCompassChange‘ is not yet implement
- 2022-09-24 深入理解C#委托delegate的使用_C#教程
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門(mén)
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支