Qt常用容器類、遍歷方法以及常用函數
Qt容器類
Qt提供了一組通用的基於模板的容器類,相比C++標準模板庫,Qt的容器更輕量安全且更容易使用。同時在速度,內存消耗和內聯代碼等方面進行了優化。
Qt容器可存儲的必須是可賦值的數據類型,也就是説這個類型必須有一個默認的構造函數、複製構造函數和一個賦值操作符。
這樣的數據包含了通常使用的大部分類型,其中包括基本數據類型,和Qt的一些數據類型(比如QString)等,不過,Qt的QObject以及其他的子類(QWidget)等是不能存儲在容器中的,但是可以通過Qt的QObject以及其他的子類的指針。
cpp
QList<QToolBar> list; //錯誤
QList<QToolBar* > list; //正確
同時Qt的容器類也是支持嵌套的
cpp
QHash<QString,QList<double> > ; //注意最後的> >一定有個空格,否則會被認為是>> 會報錯
Qt容器的兩種遍歷方式:JAVA型和STL型 ,推薦使用STL(通用且效率高)
QList類、QLinkedList類和QVector類
經常使用的容器類有QList類、QLinkedList類和QVector類等,從效率上看的話 這裏列出了他們三個的時間複雜度比較:
容器類 | 查 找 | 插 入 | 頭 部 添 加 | 尾 部 添 加
---|---|---|---|---
QList|O(1)|O(n)|Amort.O(1)|Amort.O(1)
QLinkedList|O(n)|O(1)|O(1)|O(1)
QVector|O(1)|O(n)|O(n)|O(1)
Amort.O(1)表示如果僅完成一次操作,可能會有O(n)行為,但是如果是多次操作,平均結果將會是O(1)
1.QList類
QList
-
QQueue
-
QStringList
-
QTestEventList
Qt提供了可以在列表中追加的QList::append()和QList::prepend()函數,還提供兩個可以插入的函數QList::insert()為了讓可執行代碼儘可能少,QList被高度優化了。
QList
對於不同的數據類型,QList
cpp
1.如果T是一個指針類型或者指針大小的類型,直接存在容器的數組中。
2.如果存儲對象的指針,則該指針指向實際存儲的對象。
例如:
-------------------------------------
#include<QDebug>
int main(){
QList<QString> list; // (a)
{
QString str("This is a test string");
list << str; // (b)
} // (c)
qDebug() << list[0] << "How are you!";
return 0;
}
-------------------------------------
(a)QList<QString> list: 聲明瞭一個QList<QString>棧對象。
(b)list << str 通過運算符將字符串存到列表中
(c)程序中使用花括號括起來的作用域表明,此時list保存的是一個對象的複製。
2.QLinkedList類
QLinkedList
QLinkedList
3.QVector類
QVector
QVector
4.Java風格迭代器遍歷
相比STL風格迭代器遍歷,JAVA更方便,但是性能消耗較大,對於每個容器類,Qt都提供兩種Java風格迭代器數據類型,即只讀訪問和讀寫訪問,可見下表
容 器 類 | 只 讀 迭 代 器 類 | 讀 寫 迭 代 器 類
---|---|---
QList
JAVA風格的迭代點在列表項的中間,而不是直接指向某個列表項,因此,他可能是在第一個列表項的前面,也可能在兩個列表中間,或者是在最後一個列表項之後。
cpp
QList<int> list;
list << 1 << 2 << 3 << 4 << 5;
QListIterator<int> it(list);
for(;it.hasNext();)
qDebug() << it.next();
結果為:1 2 3 4 5
上面演示的是向後遍歷,向前遍歷的函數有下面這幾種
QListIterator
::toBack(); 將迭代點移動到最後一個列表項的後面 QListIterator
::hasPrevious(); 檢查當前迭代點之前是否具有列表項 QListIterator
::previous(); 返回前一個列表項的內容並將迭代點移動到前一個列表項之前
除此之外,QListIteratorcpp
toFront(); //移動迭代點到最前面
peekNext(); //返回下一個列表項,但是不移動迭代點
peekPrevious(); //返回前一個列表項,但是不移動迭代點
findNext(); //向後查找特定列表項,有就true沒有就false,如果沒有,迭代點在列表最後面
findPrevious(); //和findNext類似,如果沒有,迭代點在列表最前面
QListIterator是隻讀迭代器,不能完成插入和刪除操作,需要使用QMutableListIterator,除去QListIterator的函數,他還有insert()插入函數,remove()刪除函數等。
QList<int> list; //空列表
QMutableListIterator<int> it(list); //讀寫迭代器
for(int i = 0; i < 10; i++)
{
it.insert(i);
}
for(it.toFront();it.hasNext();)
{
qDebug() << it.next();
}
for(it.toBack();it.hasPrevious();)
{
if(it.previous() %2 == 0)
it.remove();
else
it.setValue(it.peekNext() * 10);
}
for(it.toFront();it.hasNext();)
{
qDebug() << it.next();
}
STL風格迭代器
容 器 類 | 只 讀 迭 代 器 類 | 讀 寫 迭 代 器 類
---|---|---
QListcpp
QList<int> list;
for(int j = 0; j < 10; j++)
{
list.insert(list.end(),j);
}
QList<int>::iterator i;
for(i = list.begin(); i != list.end(); ++i)
{
qDebug() << (*i);
*i = (*i) * 10;
}
QList<int>::const_iterator ci;
for(ci=list.constBegin();ci!=list.constEnd();++ci)
{
qDebug() << *ci;
}
QMap類和QHash類
QMap類和QHash類具有非常類的的功能,他們的差別在於: - QHash具有比QMap更加的查找速度 - QHash以任意的順序存儲數據項,而QMap總是按照Key的順序存儲數據 - QHash的鍵類型Key必須提供ioeartir==()和一個全局的qHash(Key)函數,而QMap必須提供operator<()函數。 兩者的複雜度
容 器 類 | 鍵 查 找 |---| 插 入 | --- ---|---|---|---|--- --- | 平均| 最壞| 平均|最壞 QMap |O(log n)|O(log n)|O(log n)|O(log n) QHash |Amort.O(1)|O(n)|Amort.O(1)|O(n)
QMap類
QMap
QHash類
他與QMap的API幾乎完全相同,維持着一張哈希表,大小與其存儲的數據項的數目相適應。
存儲一鍵多值的數據時,也可以使用QMultiHash
Java風格迭代器的兩種分類
容 器 類 | 只 讀 迭 代 器 類 | 讀 寫 迭 代 器 類
---|---|---
QMap
STL風格迭代器的兩種分類
容 器 類 | 只 讀 迭 代 器 類 | 讀 寫 迭 代 器 類
---|---|---
QMap
QMap<QString,QString>::const_iterator cit;
for(cit = map.constBegin();cit != map.constEnd();++cit)
{
qDebug() << " " << cit.key() << " " << cit.value();
}
QMap<QString,QString>::iterator it;
it=map.find("111");
if(it != map.end())
{
it.value() = "ddd";
}
QMap<QString,QString>::const_iterator ccit;
for(ccit = map.constBegin();ccit != map.constEnd();++ccit)
{
qDebug() << " " << ccit.key() << " " << ccit.value();
}
```