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();
}
```