QT中的数据结构(一)

在做Qt项目的时候,不要去用那些数组了,要用容器。用Qt专有的数据类型。QString和std::string是有区别的。

QString

标准C++提供了两种字符串一种以\为结尾的字符数组即C风格字符串另外一种是std::string.

Qt提供了自己实现的 QString.功能更强大


QString 是由一系列Qchar组成的字符串.QString使用两个字节16 位表示一个字符。

使用的是UTF-16 双字节编码。 我们常见的编码比如UTF8.UTF8字符长度不固定导致字符串操作效率不高.

QtString 采用固定长度字符单元UTF16进行编码,字符串比较查询效率更高一些
QString采用的是UTF16,C++标准采用的是UTF8编码,Qt针对 C++标准字符串提供了QByteArray类来操作UTF8编码的本地字符串字节数组等。


QString的优势:

  1. 使用隐式共享(写时复制)减少内存使用避免不必要的数据复制减少CPU内存资源开销,提高效率;
  2. 更多的操作、 查询、 转换函数以及高效的内存分配优化;
  3. 不用担心内存分配以及 \0结尾,QString 中间可以包含\0  .length()函数返回整个字符串长度

具体使用

.append() 和 + 运算符用法和效果是一样的。

QVector


Qt容器提供动态数组数据结构跟std::vector类似性能,跟std::vector接近。

QVector基于动态数组,在内存中,QVector元素是连续存储的。

OVector适用于对访问速度要求较高的场景。

QVector内存分配采用预分配策略。向QVector添加元素的时候,如果内存不足,QVector会重新分配一块更大的内存并将原有的数据复制到新内存空间。

为了减少内存分配复制操作的开销,QVector通常会预留一定的额外空间,这就意味着QVector 实际容量大于当前存储数据的容量。

QVector删除元素时,通常不会立即释放内存,这样做是为了避免频繁的内存分配释放操作。

QVector的优点:随机访问、 连续存储、 自动扩容。

缺点: 插入删除性能差,预分配策略可能导致资源浪费,不支持节点存储,在频繁插入删除的场景下不如QLinkedList效率高。

QList


QList 是 Qt 框架中的一个动态数组容器,它提供了对元素的高效操作,并支持动态增长和收
缩。

QList 的实现原理基于动态数组,但也包含了一些优化,使其适用于不同的应用场景。

数组结构:QList 内部使用数组 (或类似数组的结构)来存储素。元素在内存中是顺序存储
的,可以通过索引直接访问元素。

std::list是基于双向链表实现,内部元素分散存储。


动态增长:当添加元素导致数组空间不足时,QList 会动态分配更大的内存空间,并将原有元
素拷贝到新的内存空间中。这样,QList 在进行添加操作时能够保持高效性能。

动态收缩:当从列表中移除元素导致数组空闲空间过多时,QList 可能会缩小内存占用,释放
多余的内存。

快速插入和删除:在列表中间插入或删除元素时,QList 可以通过移动元素实现,而不是简单
地进行插入或删除操作。这样做的好处是减少了元素移动的次数,提高了性能。

优势:

随机访问速度快:由于元素是顺序存储的,QList 提供了常数时间的随机访问速度。

动态增长和收缩: QList 可以自动调整内存大小,适应不同的数据量,使其适用于动态变化的情况。
插入和删除效率较高: QList 在插入和删除操作时采用了一些优化策略,可以提供相对高效的性能。

劣势:

内存占用:由于 QList 是动态数组,可能会存在一些额外的内存占用,尤其是在数组空间动态
增长和收缩时。非线程安全: QList 不是线程安全的。在多线程环境中使用时,需要考虑同步机制。

使用建议:
对于小规模数据:当数据量较小时,QList 提供了方便的操作和较小的性能开销。对于大规模数据
当数据量较大时,考虑使用 QVector 或 QLinkedList,这些类在特定场景下可能提供更好的性能。

多线程环境:在多线程环境中,需要谨慎使用 QList,可以考虑使用 QReadWriteLock 或其他同步机制确保线程安全。

总体而言,QList 是一个通用的、易于使用的容器类,适用于许多应用场景。在选择容器类时,建议根据具体的需求和性能特征选择合适的容器。

    QList nameList;
    nameList<<"Jimmy"<<"Green"<<"Curry";
    for(const QString& name: nameList)
    {
        qDebug()<<"name:"<::iterator it;
    for(it=nameList.begin();it!=nameList.end();++it)
    {
        qDebug()<<"name:"<<*it;
    }

QLinkedList


QLinkedList 是 Qt 框架中提供的双向链表容器,用于存储和操作元素。

与 QList 不同,QLinkedList 使用链表而不是数组来组织元素。

实现原理:

双向链表结构: QLinkedList 内部使用双向链表来存储元素。每个节点包含一个数据元素以及指向前一个和后一个节点的指针节点

插入和删除:在链表中插入和删除节点的操作是高效的,不需要移动大量元素。这使得在链表中间插入或删除元素相对容易。

无需连续内存:由于链表的特性,QLinkedList 不要求元素在内存中是连续存储的,这在动态变化的场景中提供了更大的灵活性。

优势:

  • 插入和删除操作高效: 在链表中插入和删除元素的操作不需要移动其他元素,因此在这些操作上 QLinkedList 相对高效。
  • 无需移动元素:当在链表中插入或删除元素时,不需要移动大量的元素,这在某些场景下比数组更为高效。
  • 无需连续内存:  QLinkedList 不要求元素在内存中是连续存储的,适用于动态变化的数据结构。

劣势:

  • 随机访问相对较慢:由于链表的结构, QLinkedList 提供的随机访问速度相对较慢,需要遍历链表。
  • 内存占用:与数组相比,链表可能存在一些额外的内存开销,每个节点需要存储指向前一个和后一个节点的指针。

使用建议:

  • 插入和删除频繁:当需要频繁进行插入和删除操作时, QLinkedList 提供了相对高效的性能。
  • 动态变化的数据结构:当数据结构需要频繁动态变化,或者不确定元素数量时,链表可能是更好的选择。
  • 随机访问较少:当随机访问的需求相对较少,而插入和删除操作更为频繁时,可以考虑使用 OLinkedList。
  • 建议直接使用std::list, QLinkedList有些东西已经过时了。

QMap QHash


QMap 和 QHash 都是 Qt 框架中提供的关联容器,用于存储键值对。它们在内部分别使用红黑树哈希表来实现。下面是它们的主要区别:

QMap: 底层实现:

  • QMap 使用红黑树(Red-Black Tree) 实现。这是一种自平衡的二叉搜索树,确保在插入和删除操作后维持树的平衡。
  • 有序性: QMap 中的元素是有序的,按键的升序排列。这使得在遍历时元素是有序的。
  • 性能特点: 插入和查找操作的时间复杂度为 (log n),其中 n 是 QMap 中元素的数量。

QHash: 底层实现:

  • QHash 使用哈希表(Hash Table)实现。哈希表使用哈希函数将键直接映射到表中的索引位置,以实现快速的插入、删除和查找。
  • 无序性:OHash 中的元素是无序的。在迭代时,素的顺序可能不同于插入的顺序。
  • 性能特点: 插入和查找操作的平均时间复杂度为 0(1),但在极端情况下可能达到 O(n)。

共同点:关联容器:

  • QMap 和 QHash 都是关联容器,用于存储键值对。
  • 迭代器:它们都提供了迭代器,可以用来遍历容器中的元素。
  • 接口相似:在接口上,它们提供了类似的成员函数来进行元素的插入、删除、查找等操作。

使用建议:

  • 如果你需要保持元素的有序性,并且希望在遍历时按键的升序排列,可以选择使用 QMap。
  • 如果对性能要求更高,不关心元素的有序性,可以选择使用 QHash 。

哈希冲突:

注意,QHash 的性能依赖于哈希函数的质量,且可能存在哈希冲突的情况。在某些场景下,可能需要自定义哈希函数。

总体而言,选择使用 QMap 还是 QHash 取决于你的具体需求。如果对元素有序性要求较高,或者需要在遍历时按键的升序排列,可以选择 QMap 。如果对性能要求更高,并且不关心元素的有序性,可以选择 QHash 。

QMultiMap  QMultiHash


QMap 和 QMultiMap 都是 Qt 架中的关联容器,用于存储键值对。它们的主要区别在于处理键冲突的方式和存储多个相同键的能力。

QMap 对于相同的键,会覆盖旧值,保持每个键在容器中唯一。 QMultiMap 允许相同的键关联多个值。

如果每个键只与一个值相关联,可以使用 QMap。如果需要一个键与多个值关联,可以使用 QMultiMap。

QHash 和 QMultiHash 都是 Qt 架中的哈希表实现的关联容器,用于存储键值对。它们的主要区别在于处理键冲突的方式和存储多个相同键的能力。

QHash 对于相同的键,会覆盖旧值,保持每个键在容器中唯一。

QMultiHash 允许相同的键关联多个值。插入相同键的多个值会形成一个键的值列表。如果每个键只与一个值相关联,可以使用 QHash。

如果需要一个键与多个值关联,可以使用 QMultiHash 。

QSet

QSet 是 Qt 提供的用于存储不重复元素的无序集合。它是一个模板类,可以存储任意数据类型的元素。
QSet 的底层实现是基于哈希表(hash table) 的数据结构。哈希表是一种能够提供高效的插入、删除和查找操作的数据结构,它通过将元素映射到一个固定范围的桶 (buckets) 中来实现这些操作。

Qt 中没有 QMultiSet。在 Qt Ot 中,你可以使用 QList 或 QVector 来实现类似于允许重复元素的集合的效果。这两个容器类都允许相同的元素出现多次,并按照插入的顺序来维护这些元素。

(Red-BlackTree) 实现std::set 是 C++ 标准库中提供的一种有序集合容器,它基于红黑树红黑树是一种自平衡二叉搜索树,确保了树的深度在可接受范围内,从而保持了插入、删除和查找操作的高效性。

容器的选择

如果你项目写 Qt比较多,跟界面,业务相关的东西比较多,那么就可以选择使用 Qt 的容器。

如果你写的是一些跨平台的代码,比如你的代码要在iOS、Android上使用,同时要在 Qt 上使用,底层一些代码,比如网络通讯,FFmpeg, OpenGL 那么推荐使用 std 容器。

最好能够做到 Qt 上层界面,业务,跟下层数据层业务进行一个分离下层数据业务做到跨平台,可以在所有平台上跑iOS AndroidLinux macOS windows.

做Qt的最高境界其实是不使用Qt.最终都使用纯c++ 来做开发。

你可能感兴趣的:(Qt音视频开发,qt,c++)