栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Qt常用容器类及常用函数

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Qt常用容器类及常用函数

Qt容器类

Qt提供了一组通用的基于模板的容器类,相比C++标准模板库,Qt的容器更轻量安全且更容易使用。同时在速度,内存消耗和内联代码等方面进行了优化。

Qt容器可存储的必须是可赋值的数据类型,也就是说这个类型必须有一个默认的构造函数、复制构造函数和一个赋值操作符。

这样的数据包含了通常使用的大部分类型,其中包括基本数据类型,和Qt的一些数据类型(比如QString)等,不过,Qt的QObject以及其他的子类(QWidget)等是不能存储在容器中的,但是可以通过Qt的QObject以及其他的子类的指针。

QList list;   //错误
QList list;   //正确

同时Qt的容器类也是支持嵌套的

QHash > ;   //注意最后的> >一定有个空格,否则会被认为是>> 会报错

Qt容器的两种遍历方式:JAVA型和STL型
,推荐使用STL(通用且效率高)

QList类、QlinkedList类和QVector类

经常使用的容器类有QList类、QlinkedList类和QVector类等,从效率上看的话 这里列出了他们三个的时间复杂度比较:

容器类查 找插 入头 部 添 加尾 部 添 加
QListO(1)O(n)Amort.O(1)Amort.O(1)
QlinkedListO(n)O(1)O(1)O(1)
QVectorO(1)O(n)O(n)O(1)

Amort.O(1)表示如果仅完成一次操作,可能会有O(n)行为,但是如果是多次操作,平均结果将会是O(1)

1.QList类

QList是迄今为止最常用的容器,他的子类有:

  • QItemSelection

  • QQueue

  • QStringList

  • QTestEventList

Qt提供了可以在列表中追加的QList::append()和QList::prepend()函数,还提供两个可以插入的函数QList::insert()为了让可执行代码尽可能少,QList被高度优化了。

QList维护了一个指针数组,该数组指向QList存储的列表项的内容,因此QList是支持基于下标的快速访问的。

对于不同的数据类型,QList会采取不同的存储策略,分为以下两种:

    1.如果T是一个指针类型或者指针大小的类型,直接存在容器的数组中。
    2.如果存储对象的指针,则该指针指向实际存储的对象。
    例如:
    -------------------------------------
    #include
    int main(){
        QList list;   // (a)
        {
            QString str("This is a test string");
            list << str;       // (b)
        }                      // (c)
        qDebug() << list[0] << "How are you!";
        return 0;
    }
    -------------------------------------
    (a)QList list: 声明了一个QList栈对象。
    (b)list << str 通过运算符将字符串存到列表中
    (c)程序中使用花括号括起来的作用域表明,此时list保存的是一个对象的复制。
2.QlinkedList类

QlinkedList是一个链式列表,以非连续的内存块保存数据。

QlinkedList不能使用下标,只能使用迭代器,与QList相比,在对一个很大的列表进行插入操作时,QlinkedList有更高的效率。

3.QVector类

QVector在相邻的内存中存储给定数类型T的一组数值,在一个QVector的前部或者中间位置进行插入操作速度是很慢的,因为会导致内存住的大量数据移动(数组)。

QVector既可以通过下标访问,也可以通过迭代器进行访问,QVector的子类有QPolygon、QPolygonF和QStack。

4.Java风格迭代器遍历

相比STL风格迭代器遍历,JAVA更方便,但是性能消耗较大,对于每个容器类,Qt都提供两种Java风格迭代器数据类型,即只读访问和读写访问,可见下表

容 器 类只 读 迭 代 器 类读 写 迭 代 器 类
QList,QQueueQListIteatorQMutableListIterator
QlinkedListQlinkedListIteatorQMutablelinkedListIterator
QVectorQVectorIteatorQMutableVectorIterator

JAVA风格的迭代点在列表项的中间,而不是直接指向某个列表项,因此,他可能是在第一个列表项的前面,也可能在两个列表中间,或者是在最后一个列表项之后。

    QList list;
    list << 1 << 2 << 3 << 4 << 5;
    QListIterator it(list);
    for(;it.hasNext();)
        qDebug() << it.next();

结果为:1 2 3 4 5

上面演示的是向后遍历,向前遍历的函数有下面这几种

QListIterator::toBack();
将迭代点移动到最后一个列表项的后面

QListIterator::hasPrevious();
检查当前迭代点之前是否具有列表项

QListIterator::previous();
返回前一个列表项的内容并将迭代点移动到前一个列表项之前

除此之外,QListIterator提供的其他函数有下面几种

toFront();  //移动迭代点到最前面
peekNext(); //返回下一个列表项,但是不移动迭代点
peekPrevious(); //返回前一个列表项,但是不移动迭代点
findNext();  //向后查找特定列表项,有就true没有就false,如果没有,迭代点在列表最后面
findPrevious(); //和findNext类似,如果没有,迭代点在列表最前面

QListIterator是只读迭代器,不能完成插入和删除操作,需要使用QMutableListIterator,除去QListIterator的函数,他还有insert()插入函数,remove()删除函数等。

    QList list;  //空列表
    QMutableListIterator 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风格迭代器
容 器 类只 读 迭 代 器 类读 写 迭 代 器 类
QList,QQueueQList::const_iteratorQList::iterator
QlinkedListQlinkedList::const_iteratorQlinkedList::iterator
QVectorQVector::const_iteratorQVector::iterator

STL风格迭代器的API是建立在指针操作基础上的,比如++可以移动到下一项,而*可以拿到迭代器指向的值。

    QList list;
    for(int j = 0; j < 10; j++)
    {
        list.insert(list.end(),j);
    }
    QList::iterator i;
    for(i = list.begin(); i != list.end(); ++i)
    {
        qDebug() << (*i);
        *i = (*i) * 10;
    }
    QList::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<()函数。
    两者的复杂度
容 器 类键 查 找插 入
平均最坏平均最坏
QMapO(log n)O(log n)O(log n)O(log n)
QHashAmort.O(1)O(n)Amort.O(1)O(n)
QMap类

QMap提供了一个类型从Key的键到类型为T的值的映射。
通常QMap的数据形式是一个键对应一个值,为了支持一键多值可以使用QMap::insertMulti()和QMap::values()函数。存储一键多值的数据时,也可以使用QMultiMap 容器,他继承于QMap。

QHash类

他与QMap的API几乎完全相同,维持着一张哈希表,大小与其存储的数据项的数目相适应。
存储一键多值的数据时,也可以使用QMultiHash 容器,他继承于QHash。当存储的数据顺序无关紧要时,推荐使用QHash。

Java风格迭代器的两种分类

容 器 类只 读 迭 代 器 类读 写 迭 代 器 类
QMap, QMultiMapQMapIteratorQMutableMapIterator
QMultiHash,QHashQHashIteratorQMutableHashIterator

STL风格迭代器的两种分类

容 器 类只 读 迭 代 器 类读 写 迭 代 器 类
QMap, QMultiMapQMap::const_iteratorQMap::iterator
QMultiHash,QHashQHash::const_iteratorQHash::iterator
    
    QMap map;
    map.insert("111","aaa");
    map.insert("222","bbb");
    map.insert("333","ccc");

    QMap::const_iterator cit;
    for(cit = map.constBegin();cit != map.constEnd();++cit)
    {
        qDebug() << " " << cit.key() << " " << cit.value();
    }
    QMap::iterator it;
    it=map.find("111");
    if(it != map.end())
    {
        it.value() = "ddd";
    }
    QMap::const_iterator ccit;
    for(ccit = map.constBegin();ccit != map.constEnd();++ccit)
    {
        qDebug() << " " << ccit.key() << " " << ccit.value();
    }
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/356828.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号