首页 > 其他分享 >Qt之容器类

Qt之容器类

时间:2023-10-30 17:11:27浏览次数:25  
标签:容器 Qt QVector 元素 QLinkedList include QList

一、容器类的概述

  Qt提供了多个基于模板的容器类,这些容器类可以用于存储指定类型的数据项,Qt的容器类比标准模板库(STL)中的容器类更轻巧、安全和易于使用。这些容器类是隐式共享和可重入的,而且它们进行了速度和存储优化,因此可以减少可执行文件的大小,此外,它们还是现场安全的,也就是说它们作为只读容器时可被多个线程访问。Qt的容器分为顺序容器和关联容器,容器迭代用于遍历容器里的数据项,Qt还提供了foreach宏用于遍历容器内的所有数据项。

二、顺序容器类

Qt的顺序容器类有QList、QLinkedList、QVector、QStack和QQueue

1.QList容器

QList 是 Qt 中的容器类,用于存储和管理元素的动态数组。它提供了高效的动态大小调整功能,支持插入、删除、查找和遍历元素。

以下是 QList 容器的介绍和使用示例:

  • QList 是一个模板类,可以存储任意类型的元素。
  • QList 支持在列表的任意位置插入、删除和访问元素,具有高效的动态大小调整功能。
  • 它提供了丰富的方法和操作,如迭代、搜索、排序、拼接等,以方便地操作列表中的元素。
  • QList 与标准 C++ 容器 std::vector 类似,但具有 Qt 特有的优化和功能。

(1).创建一个QList并添加元素

QList<QString> myList;
myList.append("Apple");
myList.append("Banana");
myList.append("Cherry");

(2).查找元素

int iIndex = myList.indexOf("Apple");
if (iIndex != -1) {
    qDebug() << "Found at index:" << iIndex;
} else {
    qDebug() << "not found";
}

(3).插入和删除元素

myList.insert(1, "Orange");
myList.removeAt(2);
myList.removeOne("Cherry");

(4).遍历容器元素

//使用at()函数遍历元素
for (int i = 0; i < myList.size(); i++) {
     //qDebug() << myList[i];
     qDebug() << myList.at(i);
}

//使用迭代器遍历元素
QList<QString>::iterator it;
for (it = myList.begin(); it != myList.end(); ++it) {
     qDebug() << *it;
}

//使用range-based for 循环遍历元素(C++11及更高版本)
for (const QString &item : myList) {
     qDebug() << item;
}

QList容器的优点:

  • 动态大小调整:QList 具有动态大小调整的能力,可以轻松地添加和删除元素,而不必担心手动分配或释放内存。

  • 高效的插入和删除:QList 对于在中间或开头插入或删除元素非常高效,因为它内部使用链表结构来维护元素。

  • 多种操作方法:QList 提供了丰富的操作方法,如迭代、搜索、排序、拼接等,方便进行元素的各种操作。

  • 容纳任意数据类型:QList 是一个模板类,可以存储任何数据类型的元素。

  • Qt 信号和槽机制:QList 在与 Qt 的信号和槽机制结合使用时非常有用,用于在数据模型中存储和管理数据,以便在界面上进行更新和显示。

QList容器的缺点:

  • 随机访问性能较差:相对于数组,QList 在随机访问元素时性能较差。如果需要频繁随机访问元素,QVector 可能更适合。

  • 额外的内存开销:QList 内部使用链表来实现元素的插入和删除,这会导致一些额外的内存开销,包括指向下一个元素的指针。

  • 不支持下标越界检查:与 std::vector 不同,QList 不会在访问超出范围的元素时抛出异常。这意味着在访问元素之前,需要自行确保索引不会越界。

  • 不支持排序时的稳定性:QList 在排序时不保证元素的相对顺序,因此在需要稳定排序的情况下,可能需要额外的工作。

总的来说,QList 在需要高效插入和删除元素以及在动态数据集中进行操作时非常有用。它适合用于管理不需要频繁随机访问的数据,特别是与 Qt 框架结合使用时。但在需要频繁随机访问的情况下,可能需要考虑使用 QVectorstd::vector 等支持连续存储的容器。  

2.QLinkedList容器

QLinkedList 是 Qt 中的容器类,它是双向链表,用于存储和管理元素的动态数据结构。双向链表是一种数据结构,其中每个元素都包含指向前一个和后一个元素的指针,这使得插入和删除操作非常高效。

以下是 QLinkedList 容器的介绍和使用示例:

特点和介绍:

  • QLinkedList 是一个模板类,可以存储任何类型的元素。
  • 它支持在列表的任意位置插入、删除和访问元素,具有高效的动态大小调整功能。
  • QLinkedList 内部使用链表结构,因此插入和删除元素的性能通常比数组高效,尤其是在中间或开头插入或删除元素时。
#include <QCoreApplication>
#include <QDebug>
#include <QLinkedList>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 创建一个 QLinkedList 并添加元素
    QLinkedList<QString> myLinkedList;
    myLinkedList << "Apple" << "Banana" << "Cherry";

    // 使用迭代器遍历元素
    QLinkedList<QString>::iterator it;
    for (it = myLinkedList.begin(); it != myLinkedList.end(); ++it) {
        qDebug() << *it;
    }

    // 使用 range-based for 循环遍历元素(C++11 及更高版本)
    for (const QString &item : myLinkedList) {
        qDebug() << item;
    }

    // 插入和删除元素
    QLinkedList<QString>::iterator found = myLinkedList.begin();
    myLinkedList.insert(++found, "Orange"); // 在 "Apple" 后插入 "Orange"
    myLinkedList.removeOne("Cherry");

    // 输出列表
    for (const QString &item : myLinkedList) {
        qDebug() << item;
    }

    return a.exec();
}

QLinkedList容器优点:

  • 高效的插入和删除:QLinkedList 在中间或开头插入或删除元素时非常高效,因为它内部使用双向链表,只需要更新相邻元素的指针。这使得插入和删除操作比数组高效。

  • 动态大小调整:与 QList 一样,QLinkedList 具有动态大小调整的能力,可以轻松添加和删除元素,而不必担心手动分配或释放内存。

  • 内存效率:相对于数组,QLinkedList 不需要在内存中保留一段连续的存储空间,因此它对内存的利用更加高效。这对于大型数据集的元素插入和删除操作非常有利。

QLinkedList容器缺点:

  • 随机访问性能较差:相对于数组,QLinkedList 在随机访问元素时性能较差。如果需要频繁随机访问元素,QVectorQList 可能更适合。

  • 额外的内存开销:虽然 QLinkedList 在内存利用方面较为高效,但它需要额外的内存来存储链表节点的指针,因此可能会导致一些额外的内存开销。

  • 不支持下标访问:与数组不同,QLinkedList 不支持使用下标来访问元素。访问元素需要使用迭代器或遍历整个链表。

  • 不支持排序时的稳定性:QLinkedList 在排序时不保证元素的相对顺序,因此在需要稳定排序的情况下,可能需要额外的工作。

总的来说,QLinkedList 在需要频繁插入和删除元素、不需要随机访问元素、并且对内存效率有一定要求的情况下非常有用。但在需要频繁随机访问元素的情况下,可能需要考虑使用 QVectorQList 等支持连续存储的容器。选择容器类时,需根据具体需求和性能要求来权衡。

3.QVector容器

QVector 它是动态数组,用于存储和管理元素。与 QLinkedList 不同,QVector 在内部使用连续的内存块来存储元素,因此对于需要频繁随机访问元素的情况,QVector 是一个更合适的选择。

以下是 QVector 容器的介绍和使用示例:

  • QVector 是一个模板类,可以存储任何类型的元素。
  • 它支持在数组的任意位置插入、删除和访问元素,具有高效的动态大小调整功能。
  • QVector 内部使用连续的内存块来存储元素,这使得随机访问元素的性能非常高。
#include <QCoreApplication>
#include <QDebug>
#include <QVector>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 创建一个 QVector 并添加元素
    QVector<QString> myVector;
    myVector.append("Apple");
    myVector.append("Banana");
    myVector.append("Cherry");

    //使用下班遍历元素
    for (int i = 0; i < myVector.size(); i++) {
        //qDebug() << myVector[i];
        qDebug() << myVector.at(i);
    }

    // 使用迭代器遍历元素
    QVector<QString>::iterator it;
    for (it = myVector.begin(); it != myVector.end(); ++it) {
        qDebug() << *it;
    }

    // 使用 range-based for 循环遍历元素(C++11 及更高版本)
    for (const QString &item : myVector) {
        qDebug() << item;
    }

    // 查找元素
    int index = myVector.indexOf("Banana");
    if (index != -1) {
        qDebug() << "Found at index:" << index;
    } else {
        qDebug() << "Not found";
    }

    // 插入和删除元素
    myVector.insert(1, "Orange");
    myVector.removeOne("Cherry");

    for (const QString &item : myVector) {
        qDebug() << item;
    }

    return a.exec();
}

QVector的优点:

  • 高效的随机访问:QVector 在随机访问元素时非常高效,因为它使用连续的内存块存储元素。这使得通过索引访问元素的性能非常好。

  • 动态大小调整:与 QListQLinkedList 类似,QVector 具有动态大小调整的能力,可以轻松添加和删除元素,而不必担心手动分配或释放内存。

  • 内存效率:相对于 QLinkedListQVector 的内存效率通常更高,因为它不需要额外的链表节点指针。

  • 支持标准算法:QVector 支持标准算法和容器操作,如排序、查找、拼接等。

QVector的缺点:

  • 插入和删除性能相对较差:与 QLinkedListQList 不同,QVector 在中间插入或删除元素时的性能较差,因为它需要将后续元素向后移动。如果需要频繁的插入和删除操作,QListQLinkedList 可能更适合。

  • 额外的内存开销:QVector 需要连续的内存块来存储元素,这可能导致额外的内存开销,尤其是在元素的数量发生变化时。

  • 不支持排序时的稳定性:与 QLinkedList 不同,QVector 在排序时不保证元素的相对顺序,因此在需要稳定排序的情况下,可能需要额外的工作。

总的来说,QVector 在需要高效随机访问元素的情况下非常有用,但在需要频繁插入和删除元素的情况下性能相对较差。根据具体需求,可以选择使用 QVectorQLinkedListQList 中的其中一个容器类,或者根据应用程序的特定需求来选择适当的容器类。

4.QStack容器

QStack 它是一个堆栈(stack)容器,用于存储元素,并遵循后进先出(LIFO,Last In, First Out)的原则。这意味着最后插入的元素将首先被弹出。

以下是 QStack 容器的介绍和使用示例:

  • QStack 是一个模板类,可以存储任何类型的元素。
  • 它支持将元素压入堆栈顶部(push)和从堆栈顶部弹出元素(pop)。
  • QStack 提供了一种简单的方式来实现后进先出的数据结构。
#include <QCoreApplication>
#include <QDebug>
#include <QStack>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 创建一个 QStack 并添加元素
    QStack<QString> myStack;
    myStack.push("Apple");
    myStack.push("Banana");
    myStack.push("Cherry");

    // 弹出并输出堆栈元素
    while (!myStack.isEmpty()) {
        QString top = myStack.pop();
        qDebug() << top;
    }

    return a.exec();
}

5.QQueue容器

QQueue 它是一个队列(queue)容器,用于存储元素,并遵循先进先出(FIFO,First In, First Out)的原则。这意味着最先插入的元素将首先被弹出。

以下是 QQueue 容器的介绍和使用示例: 

#include <QCoreApplication>
#include <QDebug>
#include <QQueue>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 创建一个 QQueue 并添加元素
    QQueue<QString> myQueue;
    myQueue.enqueue("Apple");
    myQueue.enqueue("Banana");
    myQueue.enqueue("Cherry");

    // 弹出并输出队列元素
    while (!myQueue.isEmpty()) {
        QString front = myQueue.dequeue();
        qDebug() << front;
    }

    return a.exec();
}

三、关联容器类  

Qt提供的关联容器有QMap、QMultiMap、QHash、QMultiHash和QSet,QMultiMap和QMultiHash支持一个键关联多个值,QHash和QMultiHash类使用散列(Hash)函数进行查找,查找速度更快。

1.QSet容器

QSet是基于散列表的集合模板类,它存储数据的顺序是不定的,查找值的速度非常快,QSet<T>内部就是用QHash实现的。它仅存不重复的元素,因此不允许重复值的存在。

#include <QCoreApplication>
#include <QDebug>
#include <QSet>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 创建一个 QSet 并添加元素
    QSet<QString> mySet;
    mySet.insert("Apple");
    mySet.insert("Banana");
    mySet.insert("Cherry");

    // 查找元素
    if (mySet.contains("Banana")) {
        qDebug() << "Banana is in the set.";
    } else {
        qDebug() << "Banana is not in the set.";
    }

    // 添加重复元素(不会重复存储)
    mySet.insert("Banana");

    // 删除元素
    mySet.remove("Cherry");

    // 遍历集合
    QSet<QString>::iterator it;
    for (it = mySet.begin(); it != mySet.end(); ++it) {
        qDebug() << *it;
    }

    // 使用范围迭代遍历集合(C++11 及更高版本)
    for (const QString &item : mySet) {
        qDebug() << item;
    }

    return a.exec();
}

2.QMap容器

QMap<Key, T>提供一个字典(关联数组),一个键映射到一个值,QMap存储数据是按照键的顺序,它提供了键值对的存储和管理,其中键唯一,每个键应对一个值,如果不在乎存储顺序,使用QHash会更快。

#include <QCoreApplication>
#include <QDebug>
#include <QMap>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 创建一个 QMap 并添加键值对
    QMap<QString, int> myMap;
    myMap["Apple"] = 5;
    myMap["Banana"] = 3;
    myMap["Cherry"] = 7;
    myMap.insert("Orange", 10);

    // 查找键值对
    if (myMap.contains("Banana")) {
        int value = myMap["Banana"];
        qDebug() << "Banana count: " << value;
    } else {
        qDebug() << "Banana not found.";
    }
    
    //表示如果在map里找到键"Banana"就返回关联的值,否则就返回指定的缺省值-1
    //int value = myMap.value("Bananas", -1);

    // 遍历键值对
    QMap<QString, int>::iterator it;
    for (it = myMap.begin(); it != myMap.end(); ++it) {
        qDebug() << it.key() << ": " << it.value();
    }

    // 使用范围迭代遍历键值对(C++11 及更高版本)
    for (const QString &key : myMap.keys()) {
        int value = myMap.value(key);
        qDebug() << key << ": " << value;
    }

    return a.exec();
}

3.QMultiMap容器

QMultiMap是QMap的子类,是用于处理多值映射的便利类,多值映射就是一个键可以对应多个值,QMap正常情况下不允许多值映射,除非使用QMap::insterMulti()添加键值对。QMultiMap是QMap的子类,所以QMap的大多数函数在QMultiMap都是可用的,但是有几个特殊的,QMultiMap::instert()等效于QMap::insertMulti(),QMultiMap::replace()等效于QMap::insert()。

#include <QCoreApplication>
#include <QDebug>
#include <QMultiMap>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 创建一个 QMultiMap 并添加键值对
    QMultiMap<QString, int> myMultiMap;
    myMultiMap.insert("Apple", 5);
    myMultiMap.insert("Banana", 3);
    myMultiMap.insert("Cherry", 7);
    myMultiMap.insert("Apple", 10); // 添加重复的键

    // 查找键值对
    if (myMultiMap.contains("Apple")) {
        QList<int> values = myMultiMap.values("Apple");
        qDebug() << "Apple counts:";
        for (int value : values) {
            qDebug() << value;
        }
    } else {
        qDebug() << "Apple not found.";
    }

    // 遍历键值对
    QMultiMap<QString, int>::iterator it;
    for (it = myMultiMap.begin(); it != myMultiMap.end(); ++it) {
        qDebug() << it.key() << ": " << it.value();
    }

    // 使用范围迭代遍历键值对(C++11 及更高版本)
    for (const QString &key : myMultiMap.uniqueKeys()) {
        QList<int> values = myMultiMap.values(key);
        qDebug() << key << " counts:";
        for (int value : values) {
            qDebug() << value;
        }
    }

    return a.exec();
}

4.QHash容器

QHash是基于散列来实现字典功能的模板,QHash<QKey, T>存储的键值对具有非常快的查找速度,QHash与QMap的功能和用法相似,区别在于以下几点:

  • QHash比QMap的查找速度快。
  • 在QMap上遍历,数据项是按照键排序的,而QHash的数据项是任意顺序的。
#include <QCoreApplication>
#include <QDebug>
#include <QHash>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 创建一个 QHash 并添加键值对
    QHash<QString, int> myHash;
    myHash.insert("Apple", 5);
    myHash.insert("Banana", 3);
    myHash.insert("Cherry", 7);

    // 查找键值对
    if (myHash.contains("Banana")) {
        int value = myHash.value("Banana");
        qDebug() << "Banana count: " << value;
    } else {
        qDebug() << "Banana not found.";
    }

    // 遍历键值对
    QHash<QString, int>::iterator it;
    for (it = myHash.begin(); it != myHash.end(); ++it) {
        qDebug() << it.key() << ": " << it.value();
    }

    // 使用范围迭代遍历键值对(C++11 及更高版本)
    for (const QString &key : myHash.keys()) {
        int value = myHash.value(key);
        qDebug() << key << ": " << value;
    }

    return a.exec();
}

5.QMultiHash容器

QMultiHash是QHash的子类,是用于处理多值映射的便利类,其用法与QMultiMap类似。

#include <QCoreApplication>
#include <QDebug>
#include <QMultiHash>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 创建一个 QMultiHash 并添加键值对
    QMultiHash<QString, int> myMultiHash;
    myMultiHash.insert("Apple", 5);
    myMultiHash.insert("Banana", 3);
    myMultiHash.insert("Cherry", 7);
    myMultiHash.insert("Apple", 10); // 添加重复的键

    // 查找键值对
    if (myMultiHash.contains("Apple")) {
        QList<int> values = myMultiHash.values("Apple");
        qDebug() << "Apple counts:";
        for (int value : values) {
            qDebug() << value;
        }
    } else {
        qDebug() << "Apple not found.";
    }

    // 遍历键值对
    QMultiHash<QString, int>::iterator it;
    for (it = myMultiHash.begin(); it != myMultiHash.end(); ++it) {
        qDebug() << it.key() << ": " << it.value();
    }

    // 使用范围迭代遍历键值对(C++11 及更高版本)
    for (const QString &key : myMultiHash.keys()) {
        QList<int> values = myMultiHash.values(key);
        qDebug() << key << " counts:";
        for (int value : values) {
            qDebug() << value;
        }
    }

    return a.exec();
}

 

标签:容器,Qt,QVector,元素,QLinkedList,include,QList
From: https://www.cnblogs.com/TechNomad/p/17798301.html

相关文章

  • Qt实现一个电子相册
    一、要实现的功能在窗口中可以显示图片,并且能够通过两个按钮进行图片的前进和后退的顺序切换。有一个按钮,通过这个按钮可以从所存图片资源中随机选取一个图片进行展示通过按钮可以控制图片自动轮播顺序切换的开始与停止,显示当前系统的时间。二、实现思路可以使用标签组件QLabel来显......
  • Qt第六十六章:展示数据的标签
    目录一、效果图二、qtDesigner①拖出一个frame作为组容器并贴上背景样式②拖出主要的三个控件:frame、line、frame、label*2③固定大小并设置字体、布局一下 ④拷贝三份并水平布局一下⑤设置样式⑥调整布局三、ui文件四、代码 一、效果图二、qtDesigner①拖出一个frame作为组容器......
  • 一、Qt简介
    1.什么是Qt?Qt是一个基于C++的图形用户界面(GUI)开发框架,但图形用户界面并不是Qt的全部,因为Qt还包含了很多非图形化的开发功能:多线程、数据库、图像图形处理、音视频处理、网络通信、文件IO等。一方面Qt可以应用于纯软件的开发,很多业界知名的软件都是使用Qt开发的,例如:另一方面,由于Qt......
  • Qt第六十五章:自定义菜单栏的隐藏、弹出
    目录一、效果图二、qtDesigner三、ui文件如下:四、代码 一、效果图二、qtDesigner原理是利用属性动画来控制QFrame的minimumWidth属性。①先拖出相应的控件②布局一下 ③填上一些样式 相关QSSbackground-color:rgb(238,242,255);border:2pxsolidrgb(255,255,255);border......
  • QTreeWidget 添加右键菜单
    有时需要为QTreeWidget的子条目添加右键菜单功能,主要有两种方案来实现:方案一该方案比较通用,通过为QTreeWidget建立信号槽,在接受itemPressed的信号时会被触发,然后判断当前是否为鼠标右键,若为鼠标右键则创建添加对应的菜单栏,并提供相应的功能。//1.QTreeWidget*tree为......
  • 请说说qt主要用的控件?信号和槽怎么实现的?
    qt主要用到的控件:QWidget基类,QPushButton普通按钮,QLineEdit文本输入,QSlider滑动条,QLabel显示文本或图像,QMainWindow创建应用程序的主窗口,QCeckBox复选框,QRadioButton单选按钮。 信号和槽的实现:每个控件可以发出信号,其它控件可以连接到这些信号的槽函数,以响应事件。......
  • 在Docker容器内,我如何连接到机器的本地主机?
    内容来自DOChttps://q.houxu6.top/?s=在Docker容器内,我如何连接到机器的本地主机?我有一个运行在Docker容器内的Nginx。我的主机系统上运行着一个MySql。我想从我的容器内连接到MySql。MySql只绑定到本地主机设备。有没有办法从这个Docker容器内连接到这个MySql或其他在本地......
  • 【Qt6】列表模型——几个便捷的列表类型
    前面一些文章,老周简单介绍了在Qt中使用列表模型的方法。很明显,使用ItemModel在许多时候还是挺麻烦的——要先建模型,再放数据,最后才构建视图。为了简化这些骚操作,Qt提供了几个便捷类。今天咱们逐个看看。一、QListWidget 这厮对应的ListView,用来显示简单的列表。要添加列......
  • 商用 LTS Qt 6.2.10 发布
    导读我们近日为商业许可证持有者发布了Qt6.2.10LTS。作为一个补丁版本,Qt6.2.10不添加任何新功能,但提供了错误修复和其他改进。你可以使用维护工具将Qt6.2.10添加到现有的在线安装中,也可以使用Qt在线安装程序进行简洁安装。离线安装程序可在Qt账户下载区下载......
  • 021-Qt 配置GitHub Copilot
    Qt配置GitHubCopilot文章目录Qt配置GitHubCopilot项目介绍GitHubCopilot配置GitHubCopilotQt前置条件升级QtGitHubCopilot前置条件激活的了GitHubCopilot账号安装Neovim启用插件,重启Qt配置GitHubCopilo安装Nodejs下载[copilot.vim](https://github.com/github/copil......