C++?Qt開發(fā)之關(guān)聯(lián)容器類使用方法詳解
引言
當(dāng)我們談?wù)摼幊讨械臄?shù)據(jù)結(jié)構(gòu)時,順序容器是不可忽視的一個重要概念。順序容器是一種能夠按照元素添加的順序來存儲和檢索數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)。它們提供了簡單而直觀的方式來組織和管理數(shù)據(jù),為程序員提供了靈活性和性能的平衡。
Qt 中提供了豐富的容器類,用于方便地管理和操作數(shù)據(jù)。這些容器類涵蓋了各種不同的用途,從簡單的動態(tài)數(shù)組到復(fù)雜的映射和集合。本章我們將主要學(xué)習(xí)關(guān)聯(lián)容器,主要包括 QMap ,QSet和 QHash,它們提供了鍵值對存儲和檢索的功能,允許通過鍵來快速查找值。
1. QMap
QMap
是 Qt 中的有序關(guān)聯(lián)容器,用于存儲鍵值對,并按鍵的升序進(jìn)行排序。以下是關(guān)于 QMap
的概述:
1.1 特點和用途
- 有序性: QMap 中的元素是有序的,按照鍵的升序進(jìn)行排列。
- 唯一鍵: 每個鍵在 QMap 中是唯一的,不允許重復(fù)鍵。
- 鍵值對存儲: 存儲鍵值對,每個鍵關(guān)聯(lián)一個值。
- 性能: 插入和查找操作的平均復(fù)雜度是 O(log n),適用于需要按鍵排序并進(jìn)行頻繁查找的場景。
1.2 函數(shù)和功能
以下是關(guān)于 QMap
常用函數(shù)及其功能的總結(jié):
函數(shù) | 功能 |
---|---|
insert(const Key &key, const T &value) | 向 QMap 中插入鍵值對。 |
insertMulti(const Key &key, const T &value) | 向 QMap 中插入允許相同鍵的多個值。 |
remove(const Key &key) | 移除指定鍵的元素。 |
value(const Key &key) const | 返回指定鍵的值。 |
contains(const Key &key) const | 判斷是否包含指定鍵。 |
isEmpty() const | 判斷 QMap 是否為空。 |
size() const | 返回 QMap 中鍵值對的數(shù)量。 |
clear() | 清空 QMap 中的所有元素。 |
keys() const | 返回 QMap 中所有鍵的列表。 |
values() const | 返回 QMap 中所有值的列表。 |
begin() | 返回指向 QMap 開始位置的迭代器。 |
end() | 返回指向 QMap 結(jié)束位置的迭代器。 |
constBegin() const | 返回指向 QMap 開始位置的常量迭代器。 |
constEnd() const | 返回指向 QMap 結(jié)束位置的常量迭代器。 |
find(const Key &key) const | 返回指向 QMap 中指定鍵的迭代器。 |
lowerBound(const Key &key) const | 返回指向 QMap 中不小于指定鍵的第一個元素的迭代器。 |
upperBound(const Key &key) const | 返回指向 QMap 中大于指定鍵的第一個元素的迭代器。 |
count(const Key &key) const | 返回指定鍵的數(shù)量。 |
toStdMap() const | 將 QMap 轉(zhuǎn)換為 std::map 。 |
這些函數(shù)提供了對 QMap
中鍵值對的插入、刪除、查找和遍歷等操作。根據(jù)需求選擇適當(dāng)?shù)暮瘮?shù)以滿足操作要求。
1.3 應(yīng)用案例
正如如下代碼所示,我們提供了QMap<QString,QString>
字典類型的關(guān)聯(lián)數(shù)組,該數(shù)組中一個鍵映射對應(yīng)一個值,QMap容器是按照順序存儲的,如果項目中不在意順序可以使用QHash
容器,使用QHash
效率更高些。
#include <QCoreApplication> #include <iostream> #include <QString> #include <QtGlobal> #include <QMap> #include <QMapIterator> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QMap<QString,QString> map; map["1001"] = "admin"; map["1002"] = "guest"; map.insert("1003","lyshark"); map.insert("1004","lucy"); // map.remove("1002"); // 根據(jù)鍵值對查詢屬性 std::cout << map["1002"].toStdString().data() << std::endl; std::cout << map.value("1003").toStdString().data() << std::endl; std::cout << map.key("admin").toStdString().data() << std::endl; // 使用STL語法迭代枚舉Map鍵值對 QMap<QString,QString>::const_iterator x; for(x=map.constBegin();x != map.constEnd(); ++x) { std::cout << x.key().toStdString().data() << " : "; std::cout << x.value().toStdString().data() << std::endl; } // 使用STL語法實現(xiàn)修改鍵值對 QMap<QString,QString>::iterator write_x; write_x = map.find("1003"); if(write_x !=map.end()) write_x.value()= "you ary in"; // 使用QTglobal中自帶的foreach遍歷鍵值對 QString each; // --> 單循環(huán)遍歷 foreach(const QString &each,map.keys()) { std::cout << map.value(each).toStdString().data() << std::endl; } // --> 多循環(huán)遍歷 foreach(const QString &each,map.uniqueKeys()) { foreach(QString x,map.value(each)) { std::cout << each.toStdString().data() << " : "; std::cout << x.toStdString().data() << std::endl; } } return a.exec(); }
上述代碼是如何使用QMap容器,其實還有一個QMultiMap容器,該容器其實是QMap的一個子集,用于處理多值映射的類,也就是說傳統(tǒng)QMap只能是一對一的關(guān)系,而QMultiMap則可以實現(xiàn)一個Key對應(yīng)多個Value或者是反過來亦可,實現(xiàn)一對多的關(guān)系。
如果總結(jié)起來可以發(fā)現(xiàn)兩者的異同點;
QMap
- 唯一鍵:
QMap
中每個鍵都是唯一的,不允許重復(fù)鍵。 - 鍵排序:
QMap
中的元素是按鍵的升序排列的。 - 使用場景: 適用于需要鍵值對有序且鍵唯一的場景。
QMultiMap
- 允許重復(fù)鍵:
QMultiMap
中可以包含重復(fù)的鍵,即多個鍵可以映射到相同的值。 - 鍵排序:
QMultiMap
中的元素是按鍵的升序排列的。 - 使用場景: 適用于允許鍵重復(fù),并且需要鍵值對有序的場景。
相同點
- 鍵值對: 都是用于存儲鍵值對的容器。
- 有序性: 元素在容器中是有序的,按鍵的升序排列。
不同點
- 鍵唯一性:
QMap
中每個鍵都是唯一的,而QMultiMap
允許重復(fù)的鍵。 - 使用場景:
QMap
適用于需要鍵唯一的情況,而QMultiMap
適用于允許鍵重復(fù)的情況。
如下所示,展示了如何使用QMultiMap
實現(xiàn)一對多的映射關(guān)系;
#include <QCoreApplication> #include <iostream> #include <QString> #include <QList> #include <QMultiMap> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QMultiMap<QString,QString> mapA,mapB,mapC,mapD; mapA.insert("lyshark","1000"); mapA.insert("lyshark","2000"); mapB.insert("admin","3000"); mapB.insert("admin","4000"); mapC.insert("admin","5000"); // 獲取到里面的所有key=lyshark的值 QList<QString> ref; ref = mapA.values("lyshark"); for(int x=0;x<ref.size();++x) { std::cout << ref.at(x).toStdString().data() << std::endl; } // 兩個key相同可相加后輸出 mapD = mapB + mapC; ref = mapD.values("admin"); for(int x=0;x<ref.size();x++) { std::cout << ref.at(x).toStdString().data() << std::endl; } return a.exec(); }
2. QHash
QHash
是一個無序的關(guān)聯(lián)容器,它存儲鍵值對,但與 QMap
不同,QHash
不會對鍵進(jìn)行排序。
2.1 特點和用途
鍵值對存儲:
QHash
中的元素以鍵值對的形式存儲,但與QMap
不同,QHash
中的元素是無序的。無序性:
QHash
中的元素是無序的,沒有特定的排列順序。唯一鍵: 每個鍵在
QHash
中是唯一的,不允許重復(fù)鍵。性能: 插入和查找操作的平均復(fù)雜度是 O(1),適用于需要快速插入和查找的場景。
2.2 函數(shù)和功能
以下是關(guān)于 QHash
常用函數(shù)及其功能的總結(jié):
函數(shù) | 功能 |
---|---|
insert(const Key &key, const T &value) | 向 QHash 中插入鍵值對。 |
insertMulti(const Key &key, const T &value) | 向 QHash 中插入允許相同鍵的多個值。 |
remove(const Key &key) | 移除指定鍵的元素。 |
value(const Key &key) const | 返回指定鍵的值。 |
contains(const Key &key) const | 判斷是否包含指定鍵。 |
isEmpty() const | 判斷 QHash 是否為空。 |
size() const | 返回 QHash 中鍵值對的數(shù)量。 |
clear() | 清空 QHash 中的所有元素。 |
keys() const | 返回 QHash 中所有鍵的列表。 |
values() const | 返回 QHash 中所有值的列表。 |
begin() | 返回指向 QHash 開始位置的迭代器。 |
end() | 返回指向 QHash 結(jié)束位置的迭代器。 |
constBegin() const | 返回指向 QHash 開始位置的常量迭代器。 |
constEnd() const | 返回指向 QHash 結(jié)束位置的常量迭代器。 |
find(const Key &key) const | 返回指向 QHash 中指定鍵的迭代器。 |
count(const Key &key) const | 返回指定鍵的數(shù)量。 |
unite(const QHash &other) | 合并兩個 QHash ,將 other 中的元素合并到當(dāng)前 QHash 。 |
intersect(const QHash &other) | 保留兩個 QHash 中共有的元素,刪除其他元素。 |
subtract(const QHash &other) | 從當(dāng)前 QHash 中移除與 other 共有的元素。 |
toStdHash() const | 將 QHash 轉(zhuǎn)換為 std::unordered_map 。 |
這些函數(shù)提供了對 QHash
中鍵值對的插入、刪除、查找和遍歷等操作。根據(jù)需求選擇適當(dāng)?shù)暮瘮?shù)以滿足操作要求。
2.3 應(yīng)用案例
QHash
與QMap
其實是一樣的,如果不需要對鍵值對進(jìn)行排序那么使用QHash
將會得到更高的效率,正是因為Hash
的無序,才讓其具備了更加高效的處理能力。
#include <QCoreApplication> #include <iostream> #include <QString> #include <QHash> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QHash<QString, QString> hash; hash["1001"] = "admin"; hash["1002"] = "guest"; hash.insert("1003", "lyshark"); hash.insert("1004", "lucy"); // hash.remove("1002"); // 根據(jù)鍵值對查詢屬性 std::cout << hash["1002"].toStdString().data() << std::endl; std::cout << hash.value("1003").toStdString().data() << std::endl; std::cout << hash.key("admin").toStdString().data() << std::endl; // 使用STL語法迭代枚舉Hash鍵值對 QHash<QString, QString>::const_iterator x; for (x = hash.constBegin(); x != hash.constEnd(); ++x) { std::cout << x.key().toStdString().data() << " : "; std::cout << x.value().toStdString().data() << std::endl; } // 使用STL語法實現(xiàn)修改鍵值對 QHash<QString, QString>::iterator write_x; write_x = hash.find("1003"); if (write_x != hash.end()) write_x.value() = "you are in"; // 使用Qt中自帶的foreach遍歷鍵值對 QString each; // --> 單循環(huán)遍歷 foreach (const QString &each, hash.keys()) { std::cout << hash.value(each).toStdString().data() << std::endl; } // --> 多循環(huán)遍歷 foreach (const QString &each, hash.uniqueKeys()) { foreach (QString x, hash.values(each)) { std::cout << each.toStdString().data() << " : "; std::cout << x.toStdString().data() << std::endl; } } return a.exec(); }
這里需要說明一點,與QMap
一樣,QHash
也能夠使用QMultiHash
其操作上與QMultiMap
保持一致,此處讀者可自行嘗試。
3. QSet
QSet
是 Qt 中的無序關(guān)聯(lián)容器,類似于 C++ 標(biāo)準(zhǔn)庫的 std::unordered_set
。它主要用于存儲唯一值,而不關(guān)心元素的順序。以下是關(guān)于 QSet
的概述:
3.1 特點和用途
- 無序性:
QSet
中的元素是無序的,沒有特定的排列順序。 - 唯一值: 每個值在
QSet
中是唯一的,不允許重復(fù)值。 - 性能: 適用于需要快速查找和檢索唯一值的場景,性能比有序容器(如
QMap
)更高。 - 底層實現(xiàn): 使用哈希表實現(xiàn),因此插入和查找操作的平均復(fù)雜度是 O(1)。
3.2 函數(shù)和功能
以下是關(guān)于 QSet
常用函數(shù)及其功能的總結(jié):
函數(shù) | 功能 |
---|---|
insert(const T &value) | 向 QSet 中插入元素。 |
contains(const T &value) const | 判斷是否包含指定元素。 |
remove(const T &value) | 移除指定元素。 |
isEmpty() const | 判斷 QSet 是否為空。 |
size() const | 返回 QSet 中元素的數(shù)量。 |
clear() | 清空 QSet 中的所有元素。 |
unite(const QSet &other) | 合并兩個 QSet ,將 other 中的元素合并到當(dāng)前 QSet 。 |
intersect(const QSet &other) | 保留兩個 QSet 中共有的元素,刪除其他元素。 |
subtract(const QSet &other) | 從當(dāng)前 QSet 中移除與 other 共有的元素。 |
begin() | 返回指向 QSet 開始位置的迭代器。 |
end() | 返回指向 QSet 結(jié)束位置的迭代器。 |
constBegin() const | 返回指向 QSet 開始位置的常量迭代器。 |
constEnd() const | 返回指向 QSet 結(jié)束位置的常量迭代器。 |
這些函數(shù)提供了對 QSet
中元素的插入、刪除、查找和遍歷等操作。QSet
是一個無序容器,用于存儲唯一的元素。根據(jù)需求選擇適當(dāng)?shù)暮瘮?shù)以滿足操作要求。
3.3 應(yīng)用案例
QSet 集合容器,是基于散列表(哈希表)的集合模板,存儲順序同樣不定,查找速度最快,其內(nèi)部使用QHash
實現(xiàn)。
#include <QCoreApplication> #include <iostream> #include <QString> #include <QSet> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QSet<QString> set; set << "dog" << "cat" << "tiger"; // 測試某值是否包含于集合 if(set.contains("cat")) { std::cout << "include" << std::endl; } return a.exec(); }
4. 嵌套案例總結(jié)
4.1 QList與QMap組合
代碼通過結(jié)合使用 QList
和 QMap
實現(xiàn)了數(shù)據(jù)的嵌套存儲。具體而言,通過在 QMap
中存儲鍵值對,其中鍵是時間字符串,而值是包含浮點數(shù)數(shù)據(jù)的 QList
。這種結(jié)構(gòu)使得可以方便地按時間檢索相關(guān)聯(lián)的數(shù)據(jù)集。
#include <QCoreApplication> #include <iostream> #include <QString> #include <QtGlobal> #include <QList> #include <QMap> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QMap<QString,QList<float>> map; QList<float> ptr; // 指定第一組數(shù)據(jù) ptr.append(10.1); ptr.append(12.5); ptr.append(22.3); map["10:10"] = ptr; // 指定第二組數(shù)據(jù) ptr.clear(); ptr.append(102.2); ptr.append(203.2); ptr.append(102.1); map["11:20"] = ptr; // 輸出所有的數(shù)據(jù) QList<float> tmp; foreach(QString each,map.uniqueKeys()) { tmp = map.value(each); std::cout << "Time: " << each.toStdString().data() << std::endl; for(qint32 x=0;x<tmp.count();x++) { std::cout << tmp[x]<< std::endl; } } return a.exec(); }
在示例中,兩組數(shù)據(jù)分別對應(yīng)不同的時間鍵,每組數(shù)據(jù)存儲在相應(yīng)的 QList
中。最后,通過迭代輸出了所有數(shù)據(jù),以時間為鍵檢索相應(yīng)的數(shù)據(jù)集,并將每個數(shù)據(jù)集中的浮點數(shù)逐個輸出。整體而言,這種數(shù)據(jù)結(jié)構(gòu)的嵌套使用有助于組織和檢索多維度的數(shù)據(jù)。
4.2 QList合并為QMap
通過使用 QList 存儲頭部信息(Header)和相應(yīng)的數(shù)值信息(Values),然后通過循環(huán)迭代將兩個列表合并為一個 QMap。在這個 QMap 中,頭部信息作為鍵,而數(shù)值作為相應(yīng)的值,形成了一個鍵值對應(yīng)的字典結(jié)構(gòu)。最后,通過 QMap 的鍵值對操作,輸出了特定字典中的數(shù)據(jù)。
#include <QCoreApplication> #include <iostream> #include <QString> #include <QtGlobal> #include <QList> #include <QMap> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QList<QString> Header = {"MemTotal","MemFree","Cached","SwapTotal","SwapFree"}; QList<float> Values = {12.5,46.8,68,100.3,55.9}; QMap<QString,float> map; // 將列表合并為一個字典 for(int x=0;x<Header.count();x++) { QString head = Header[x].toStdString().data(); float val = Values[x]; map[head] = val; } // 輸出特定字典中的數(shù)據(jù) std::cout << map.key(100.3).toStdString().data() << std::endl; std::cout << map.value("SwapTotal") << std::endl; return a.exec(); }
整體而言,這樣的數(shù)據(jù)結(jié)構(gòu)使得能夠更方便地按照特定的頭部信息檢索相應(yīng)的數(shù)值。
4.3 QMap拆分為QList
這段代碼演示了如何使用 QMap 存儲鍵值對,并分別將鍵和值存儲到兩個 QList 中。首先,通過 Display 函數(shù)輸出了 QMap 中的鍵值對。
接著,通過 map.keys() 和 map.values() 分別獲取 QMap 中的所有鍵和值,將它們存儲到兩個 QList 中,并使用循環(huán)分別輸出了這兩個列表的內(nèi)容。
#include <QCoreApplication> #include <iostream> #include <QString> #include <QtGlobal> #include <QList> #include <QMap> void Display(QMap<QString,float> map) { foreach(const QString &each,map.uniqueKeys()) { std::cout << each.toStdString().data() << std::endl; std::cout << map.value(each) << std::endl; } } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QMap<QString,float> map; map["MemTotal"] = 12.5; map["MemFree"] = 32.1; map["Cached"] = 19.2; Display(map); QList<QString> map_key; QList<float> map_value; // 分別存儲起來 map_key = map.keys(); map_value = map.values(); // 輸出所有的key值 for(int x=0;x<map_key.count();x++) { std::cout << map_key[x].toStdString().data() << std::endl; } // 輸出所有的value值 for(int x=0;x<map_value.count();x++) { std::cout << map_value[x] << std::endl; } return a.exec(); }
4.4 QList結(jié)構(gòu)體排序
實現(xiàn)對包含結(jié)構(gòu)體 MyStruct
的 QList
進(jìn)行排序,并輸出排序后的結(jié)果。首先,定義了一個包含整數(shù)的 QList
,通過 std::sort
函數(shù)按從大到小的順序?qū)υ摿斜磉M(jìn)行排序,并使用 Display
函數(shù)輸出排序后的結(jié)果。
其次,定義結(jié)構(gòu)體 MyStruct
,其中包含兩個成員變量 uuid
和 uname
。創(chuàng)建一個存儲該結(jié)構(gòu)體的 QList
,并添加了幾個結(jié)構(gòu)體對象。通過 devListSort
函數(shù),以結(jié)構(gòu)體的 uuid
成員進(jìn)行排序,并使用循環(huán)輸出排序后的結(jié)果。
#include <QCoreApplication> #include <iostream> #include <QString> #include <QtGlobal> #include <QList> struct MyStruct { int uuid; QString uname; }; void Display(QList<int> ptr) { foreach(const int &each,ptr) std::cout << each << " "; std::cout << std::endl; } // 由大到小排列 int compare(const int &infoA,const int &infoB) { return infoA > infoB; } // 針對結(jié)構(gòu)體的排序方法 void devListSort(QList<MyStruct> *list) { std::sort(list->begin(),list->end(),[](const MyStruct &infoA,const MyStruct &infoB) { return infoA.uuid < infoB.uuid; }); } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // 定義并對單一數(shù)組排序 QList<int> list = {56,88,34,61,79,82,34,67,88,1}; std::sort(list.begin(),list.end(),compare); Display(list); // 定義并對結(jié)構(gòu)體排序 QList<MyStruct> list_struct; MyStruct ptr; ptr.uuid=1005; ptr.uname="admin"; list_struct.append(ptr); ptr.uuid=1002; ptr.uname = "guest"; list_struct.append(ptr); ptr.uuid = 1000; ptr.uname = "lyshark"; list_struct.append(ptr); devListSort(&list_struct); for(int x=0;x< list_struct.count();x++) { std::cout << list_struct[x].uuid << " ---> "; std::cout << list_struct[x].uname.toStdString().data() << std::endl; } return a.exec(); }
上述這段代碼演示了如何對一個包含整數(shù)的列表和一個包含結(jié)構(gòu)體的列表進(jìn)行排序,并輸出排序后的結(jié)果。在結(jié)構(gòu)體排序的情況下,使用了自定義的排序方法 devListSort
,該方法按照結(jié)構(gòu)體的 uuid
成員進(jìn)行升序排序。
以上就是C++ Qt開發(fā)之關(guān)聯(lián)容器類使用方法詳解的詳細(xì)內(nèi)容,更多關(guān)于C++ Qt關(guān)聯(lián)容器類使用的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++實現(xiàn)百度坐標(biāo)(BD09)及GCJ02與WGS84之間的轉(zhuǎn)換
這篇文章主要為大家詳細(xì)介紹了C++實現(xiàn)百度坐標(biāo)(BD09)及GCJ02與WGS84之間的轉(zhuǎn)換的方法,文中的示例代碼講解詳細(xì),希望對大家有所幫助2023-03-03udp socket客戶端和udp服務(wù)端程序示例分享
這篇文章主要介紹了udp socket客戶端和udp服務(wù)端程序示例,需要的朋友可以參考下2014-03-03C語言統(tǒng)計一篇英文短文中單詞的個數(shù)實例代碼
本文通過實例代碼給大家介紹的C語言統(tǒng)計一篇英文短文中單詞的個數(shù),代碼簡單易懂,非常不錯,具有參考借鑒價值,需要的朋友參考下吧2018-03-03c++ std::invalid_argument應(yīng)用
想研究std::invalid_argument的朋友可以參考下2013-01-01