在C++裡做大型程式時,少不了要與數組、連結清單等資料結構打交道。就是最簡單的字元串也常常讓頭痛萬分,Qt中有QString解決了字元串的頭痛,那麼其他數組等有沒有更簡單的解決方案呢?Qt作為一款優秀的類型庫,當然不會沒考慮這些。Qt提供了大量的“容器類”,專門用于以某種方式存儲大量内容,QString其實隻是這大量的容器類的一種。
我在這裡介紹:
QVector(數組)、QLinkedList(連結清單)、QMap(映射表)、QHash(哈希表)
QVector,是Qt對所有數組的封裝,比如我們想要一個int類型數組,我們原先會寫int array[10],我們在Qt裡可以寫QVector<int> array(10)
指派的時候,我們依然可以照舊array[5]=4;想擷取某一項的值也還可以array[9],也就是說,原來的特性我們還可以用。
那麼QVector有什麼好處呢?
·我們可以用count函數獲知數組中有多少個元素,友善周遊
·原先我們必須預定義好大小,而用QVector我們雖然最好也先定義好大小,但是預先不定義也可以。
我們可以使用append函數或者<<操作符來在數組最後端添加元素而不用擔心溢出問題。
<code>QVector<</code><code>double</code><code>> vect(2);</code>
<code>vect[0] = 1.0;</code>
<code>vect[1] = 2.0;</code>
<code>for</code> <code>(</code><code>int</code> <code>i = 0; i < vect.count(); ++i) {</code>
<code> </code><code>cout << vect[i] << endl;</code>
<code>}</code>
<code> </code><code>cout << vect.at(i) << endl;</code>
要使用索引方式設定元素,必須先配置好夠長的空間,否則會發生超出索引範圍的錯誤,使用[]運算子指定索引存取的方式是比較友善,但在某些場合下,使用at()方法會較有效率一些,這涉及Qt的隱式共享機制,稍後再作介紹。
您也可以使用QVector的append()方法來加入元素,使用remove()方法來移除元素,使用insert()方法來插入元素,例如append()的使用如下:
vect.append(3.0);vect.append(4.0);
或者是使用<<運算子附加元素:
vect << 5.0 << 6.0;
QVector 也重載了一些其它的運算子,以及提供了一些其它可用的方法,請查詢Qt線上檔案有關於QVector的介紹。QVector提供的是鄰接的 記憶體空間以存取物件,是以對於循序存取或使
QList 的子類別QStringList為Qt中應用很廣的類別,可以讓您儲存QString物件,QList的子類別QQueue則提供了佇列結構的容器管理。
以上先列出QVector、QLinkedList及QList的使用比較:
如果想要有連續鄰接的記憶體空間來存放元件,則使用QVector 。
如果需要真正的鏈結資料結構,並使用基於疊代器的存取方式,則使用QLinkedList 。
在大部份情況下,QList 可以滿足快速存取、插入、移除的需求,並可提供基於索引的存取方式。
<code>QList<QString> list;</code>
<code>list <<</code><code>"caterpillar"</code> <code><<</code><code>"momor"</code> <code><<</code><code>"bush"</code><code>;</code>
<code> </code>
<code>QListIterator<QString> iterator(list);</code>
<code>while</code> <code>(iterator.hasNext()) {</code>
<code> </code><code>cout << iterator.next().toAscii().data() << endl;</code>
與Java 疊代器類似的,hasNext()測試是否有下一個元素,next()傳回下一個元素,其它還有hasPrevious()、previous()等方法 可以使用。Java風格的疊代器有兩種:唯讀與可讀寫。QListIterator是唯讀疊代器,對於可讀寫疊代器,命名上會加上Mutable,例 如QMutableListIterator,除了next()、previous()等方法之外,還提供了insert()、remove()等方法可 以使用,例如:
<code>QLinkedList<QString> list;</code>
<code> </code><code>list <<</code><code>"caterpillar"</code> <code><<</code><code>"momor"</code> <code><<</code><code>"bush"</code><code>;</code>
<code> </code><code>QMutableLinkedListIterator<QString> rwIterator(list);</code>
<code>while</code> <code>(rwIterator.hasNext())</code>
<code> </code><code>{</code>
<code> </code><code>if</code><code>(rwIterator.next() ==</code><code>"momor"</code><code>)</code>
<code> </code><code>{ rwIterator.insert(</code><code>"bee"</code><code>); </code>
<code> </code><code>break</code><code>;</code>
<code>QLinkedListIterator<QString> rIterator(list);</code>
<code>while</code> <code>(</code>
<code>rIterator.hasNext()</code>
<code>)</code>
<code>{ cout << rIterator.next().toAscii().data() << endl;</code>
QMap是個有趣的東西,想在裸露的底層C++實作它頗為麻煩。數組建立的是從0開始的連續數字與資料的對應關系,而QMap的作用就是,讓任意一種資料類型對應于另一種資料類型。聲明時如此:QMap<索引類型,資料類型> 變量名。他的表現有點類似于PHP程式設計的array
比如:
<code>#include<QMap></code>
<code>...</code>
<code>void</code> <code>someFunction()</code>
<code>{</code>
<code> </code><code>QMap<QString,QString> map;</code>
<code> </code><code>map[</code><code>"Hello"</code><code>]=</code><code>"World"</code><code>;</code>
<code> </code><code>QMap<</code><code>int</code><code>,</code><code>double</code><code>> i2d;</code>
<code> </code><code>i2d[5231]=32.4213;</code>
<code> </code><code>//周遊比較特殊,得這樣:</code>
<code> </code><code>QMapIterator<QString,QString> i(map);</code>
<code> </code><code>while</code><code>(i.hasNext())</code>
<code> </code><code>doSomething(i.next());</code>
如果我們想用[]操作符通路某一項,但那一項并不存在,那就會自動建立,如果不想建立空白項可以使用value函數,如i2d.value(123,-0.1);這裡如果i2d[123]存在的話就傳回那一項,否則傳回預設值-0.1,這個預設值可以不寫,那樣Qt系統就會使用Qt預設的預設值……。可以用take函數(讓人糾結的函數名)來删除某一項。
QHash哈希表,與QMap幾乎一樣,但是它更高效,不過使用QHash要求作為索引的類型可以用==比較并且有對應的函數qHash,Qt裡面自帶了一部分,比如QString、各類整數、指針、QByteArray、QChar等都可以直接作為QHash的索引。因為QHash更高效,是以建議盡量使用QHash。
QMap與QHash都是一對一或多對以的映射,可以使用QMultiMap與QMultiHash建立一對多的映射。
比如QMultiMap <int,QString> map;
map[3]="Hello";
map.insert(3,"World");
調用map[3]時,就會得到一個QList<QString>類型的變量。
周遊時依然可用 QMapIterator
本文介紹的是Qt QHash 和QMap的差別,關于容器類可以查閱更多的資料,首先我們先把QHash 和QMap區分開來。内容如下。
QMap提供了一個從類項為key的鍵到類項為T的直的映射,通常所存儲的資料類型是一個鍵對應一個直,并且按照Key的次序存儲資料,這個類也支援一鍵多值的情況,用類QMultiMap
QHash具有和QMap幾乎完全一樣的APi,此類維護這一張哈希表,表的大小和資料項是自适應的,QHash是以任意的順序住址他的資料,,當然了他也是可以支援一鍵多值的,QMultiHash
兩種之間的差別是:
QHash查找速度上顯著于QMap
QHash以任意的方式進行存儲,而QMap則是以key順序進行存儲.
Qhash 的鍵類型必須提供operator==()和yige 全局的qHash(key)函數。而QMap的鍵類型key必須提供operator<()函數.
他們同樣也是有兩種風格的疊代容器。用來進行周遊的。
STL 風格的
QMap<key,T> QMap<key,T>::const_iterator QMap<key,T>::iterator//同樣中間那個也是隻讀的,最後那個是讀寫的。下面以一個例子來進行說明:
<code>1.#include <QDebug></code>
<code>2.</code><code>int</code> <code>main(</code><code>int</code> <code>argc,</code><code>char</code> <code>*argv[])</code>
<code>3.{</code>
<code>4. QMap<QString, QString> map;</code>
<code>5. map.insert(</code><code>"beijing"</code><code>,</code><code>"111"</code><code>);</code>
<code>6. map.insert(</code><code>"shanghai"</code><code>,</code><code>"021"</code><code>);</code>
<code>7. map.insert(</code><code>"tianjin"</code><code>,</code><code>"022"</code><code>);</code>
<code>8. map.insert(</code><code>"chongqing"</code><code>,</code><code>"023"</code><code>);</code>
<code>9. map.insert(</code><code>"jinan"</code><code>,</code><code>"0531"</code><code>);</code>
<code>10. map.insert(</code><code>"wuhan"</code><code>,</code><code>"027"</code><code>);</code>
<code>11.QMap<QString, QString>::const_iterator i;</code>
<code>12.</code><code>for</code><code>( i=map.constBegin(); i!=map.constEnd(); ++i)</code>
<code>13. qDebug() <<i.key() <<</code><code>" "</code> <code><<i.value();</code>
<code>14. QMap<QString, QString>::iterator mi;</code>
<code>15.mi = map.find(</code><code>"beijing"</code><code>);</code>
<code>16.</code><code>if</code><code>(mi != map.end())</code>
<code>17. mi.value() =</code><code>"010"</code><code>;</code>
<code>18. QMap<QString, QString>::const_iterator modi;</code>
<code>19. qDebug() <<</code><code>""</code><code>;</code>
<code>20.</code><code>for</code><code>( modi=map.constBegin(); modi!=map.constEnd(); ++modi)</code>
<code>21. qDebug() <<modi.key() <<</code><code>" "</code> <code><<modi.value();</code>
<code>22.</code><code>return</code> <code>0;</code>
<code>23.}</code>
小結:關于Qt 中QHash 和QMap的差別,相信你看完之後,應該很了然一新了。如果你需要對記憶體配置設定做優化,Qt的容器提供了三大記憶體配置設定函數,reserve(size),顯示預配置設定size的記憶體; capacity(),傳回已配置設定記憶體;squeeze()釋放所有的未占用的記憶體;當你知道QHash的大小時,可以使用reserve函數預先配置設定記憶體。
今天我們來說說Qt容器類中的關聯存儲容器。所謂關聯存儲容器,就是容器中存儲的一般是二進制組,而不是單個的對象。二進制組一般表述為,也就是“鍵-值對”。
首先,我們看看數組的概念。數組可以看成是一種形式的鍵-值對,它的Key隻能是int,而值的類型是Object,也就是任意類型(注意,這裡我們隻是說數組可以是任意類型,這個Object并不必須是一個對象)。現在我們擴充數組的概念,把Key也做成任意類型的,而不僅僅是int,這樣就是一個關聯容器了。如果學過資料結構,典型的關聯容器就是散列(Hash Map,哈希表)。Qt提供兩種關聯容器類型:QMap和QHash。
QMap是一種鍵-值對的資料結構,它實際上使用跳表skip-list實作,按照K進行升序的方式進行存儲。使用QMap的insert()函數可以向QMap中插入資料,典型的代碼如下:
QMap map;
map.insert("eins", 1); map.insert("sieben", 7);
map.insert("dreiundzwanzig", 23);
同樣,QMap也重載了[]運算符,你可以按照數組的複制方式進行使用:
map["eins"] = 1;
map["sieben"] = 7;
map["dreiundzwanzig"] = 23;
[]操作符同樣也可以像數組一樣取值。但是請注意,如果在一個非const的map中,使用[]操作符取一個不存在的Key的值,則這個Key會被自動建立,并将其關聯的value賦予一個空值。如果要避免這種情況,請使用QMap的value()函數:
int val = map.value("dreiundzwanzig");
如果key不存在,基本類型和指針會傳回0,對象類型則會調用預設構造函數,傳回一個對象,與[]操作符不同的是,value()函數不會建立一個新的鍵-值對。如果你希望讓不存在的鍵傳回一個預設值,可以傳給value()函數第二個參數:
int seconds = map.value("delay", 30);
這行代碼等價于:
int seconds = 30;
if (map.contains("delay"))
seconds = map.value("delay");
QMap中的K和T可以是基本資料類型,如int,double,可以是指針,或者是擁有預設構造函數、拷貝構造函數和指派運算符的類。并且K必須要重載<運算符,因為QMap需要按K升序進行排序。
QMap提供了keys()和values()函數,可以獲得鍵的集合和值的集合。這兩個集合都是使用QList作為傳回值的。
Map是單值類型的,也就是說,如果一個新的值配置設定給一個已存在的鍵,則舊值會被覆寫。如果你需要讓一個key可以索引多個值,可以使用QMultiMap。這個類允許一個key索引多個value,如:
QMultiMap multiMap;
multiMap.insert(1, "one"); multiMap.insert(1, "eins");
multiMap.insert(1, "uno");
QList vals = multiMap.values(1);
QHash是使用散列存儲的鍵-值對。它的接口同QMap幾乎一樣,但是它們兩個的實作需求不同。QHash的查找速度比QMap快很多,并且它的存儲是不排序的。對于QHash而言,K的類型必須重載了==操作符,并且必須被全局函數qHash()所支援,這個函數用于傳回key的散列值。Qt已經為int、指針、QChar、QString和QByteArray實作了qHash()函數。
QHash會自動地為散列配置設定一個初始大小,并且在插入資料或者删除資料的時候改變散列的大小。我們可以使用reserve()函數擴大散列,使用squeeze()函數将散列縮小到最小大小(這個最小大小實際上是能夠存儲這些資料的最小空間)。在使用時,我們可以使用reserve()函數将資料項擴大到我們所期望的最大值,然後插入資料,完成之後使用squeeze()函數收縮空間。
QHash同樣也是單值類型的,但是你可以使用insertMulti()函數,或者是使用QMultiHash類來為一個鍵插入多個值。另外,除了QHash,Qt也提供了QCache來提供緩存,QSet用于僅存儲key的情況。這兩個類同QHash一樣具有K的類型限制。
周遊關聯存儲容器的最簡單的辦法是使用Java風格的周遊器。因為Java風格的周遊器的next()和previous()函數可以傳回一個鍵-值對,而不僅僅是值,例如:
QMap map; ...
int sum = 0; QMapIterator i(map); while (i.hasNext())
sum += i.next().value();
如果我們并不需要通路鍵-值對,可以直接忽略next()和previous()函數的傳回值,而是調用key()和value()函數即可,如:
QMapIterator i(map);
while (i.hasNext()) { i.next();
if (i.value() > largestValue) { largestKey = i.key();
largestValue = i.value(); } }
Mutable周遊器則可以修改key對應的值:
QMutableMapIterator i(map);
while (i.hasNext()) { i.next(); if (i.value() < 0.0)
i.setValue(-i.value()); }
如果是STL風格的周遊器,則可以使用它的key()和value()函數。而對于foreach循環,我們就需要分别對key和value進行循環了:
QMultiMap map; ...
foreach (QString key, map.keys()) {
foreach (int value, map.values(key)) { doSomething(key, value);
} }
本文轉自夜&楓部落格園部落格,原文連結:http://www.cnblogs.com/newstart/archive/2013/05/09/3068625.html,如需轉載請自行聯系原作者