QLinkedList

1.QLinkedList

QLinkedList是Qt框架中的一个容器类,它实现了一个双向链表。Qt框架是一个跨平台的应用程序开发框架,广泛应用于GUI和非GUI程序的开发。QLinkedList提供了一个高效的数据结构,用于存储和管理元素的集合。以下是对QLinkedList的详细介绍:

1. 基本特性

  • 动态大小QLinkedList的大小是动态的,可以根据需要轻松添加或删除元素。这使得它在处理具有不确定大小的数据集时非常有用。
  • 双向遍历:与QVectorQList不同,QLinkedList允许从头到尾以及从尾到头的双向遍历。这种遍历方式在某些场景下会非常有用。
  • 高效的插入和删除操作:在链表的中间插入或删除元素的时间复杂度为O(1)。这使得QLinkedList在需要频繁插入和删除元素的场景中,具有优势。
  • 不需要连续内存QLinkedList的元素不需要存储在连续的内存空间中。这意味着在内存碎片化的情况下,QLinkedList可能更容易分配内存。
  • 模板类QLinkedList是一个模板类,可以存储任意类型的元素。要使用QLinkedList,需要包含<QLinkedList>头文件,并用所需类型的模板参数实例化它。

2. 主要操作

  • 创建和初始化:可以通过默认构造函数或初始化列表来创建和初始化QLinkedList
  • 插入元素:提供了append(在末尾添加元素)、prepend(在开头添加元素)和insert(在指定位置插入元素)等方法。
  • 移除元素:支持移除指定位置的元素、移除特定值的元素以及清空链表等操作。
  • 遍历元素:可以使用迭代器或范围循环来遍历QLinkedList中的元素。
  • 其他常用方法:包括获取链表大小、检查链表是否为空、访问第一个和最后一个元素等。

3. 使用场景

  • 频繁插入和删除QLinkedList在中间插入和删除元素时非常高效,适合频繁进行这种操作的场景。
  • FIFO队列:可以用QLinkedList来实现先进先出队列,使用prepend添加元素,使用takeLast提取元素。
  • 需要双向遍历:由于QLinkedList是双向链表,可以在需要双向遍历的情况下使用。

4. 与其他容器类的对比

  • 与QList对比QList通常基于数组实现,支持常数时间复杂度的随机访问,但在中间或头部插入和删除时可能需要移动数组中的元素,时间复杂度为O(n)。而QLinkedList插入和删除操作的时间复杂度为O(1),但随机访问效率较低,时间复杂度为O(n)。
  • 与QVector对比QVector也基于数组实现,与QList类似,但它在某些情况下可能使用不同的内存分配策略。与QLinkedList相比,QVector的元素占据相邻内存空间,但在中间插入和删除元素时效率较低。

5. 注意事项

  • 已弃用信息:值得注意的是,在最新的Qt版本中(如Qt 6),QLinkedList已经被标记为已弃用,并建议使用std::list替代,因为它提供了类似的功能,并且与C++标准库更兼容。如果您的代码基已经使用了QLinkedList,或者您有特定的理由需要使用它(例如,与老版本的Qt代码兼容),那么可以继续使用它,但建议针对新项目使用标准库中的容器。

综上所述,QLinkedList是Qt框架中提供的一个双向链表容器类,它适用于频繁插入和删除操作的场景,并且支持双向遍历。然而,随着Qt版本的更新,它可能已被弃用,并建议使用标准库中的容器替代。

2.QLinkedList常用接口 

QLinkedList是Qt框架中的一个双向链表容器类,它提供了一系列丰富的接口用于元素的插入、删除、遍历和查询等操作。以下是一些常用的QLinkedList接口:

1. 构造函数与析构函数

  • 构造函数QLinkedList() 默认构造函数,创建一个空的链表。

2. 插入操作

  • append(const T &value):在链表末尾添加一个元素。
  • prepend(const T &value):在链表开头添加一个元素。
  • insert(int i, const T &value):在链表的指定位置插入一个元素。位置索引从0开始,如果位置i大于链表的当前大小,则元素将被添加到链表的末尾。

3. 删除操作

  • removeFirst():移除链表中的第一个元素并返回该元素。如果链表为空,则行为未定义。
  • removeLast():移除链表中的最后一个元素并返回该元素。如果链表为空,则行为未定义。
  • removeOne(const T &value):移除链表中第一个与指定值相等的元素,如果成功移除则返回true,否则返回false。
  • removeAll(const T &value):移除链表中所有与指定值相等的元素,并返回移除的元素个数。
  • clear():清空链表,移除链表中的所有元素。

4. 访问与遍历

  • isEmpty() const:返回链表是否为空。
  • first():返回链表中第一个元素的引用。如果链表为空,则行为未定义。
  • last():返回链表中最后一个元素的引用。如果链表为空,则行为未定义。
  • const_iterator begin() const:返回指向链表第一个元素的常量迭代器。
  • const_iterator end() const:返回指向链表末尾的常量迭代器。
  • iterator begin():返回指向链表第一个元素的迭代器。
  • iterator end():返回指向链表末尾的迭代器。

5. 查找与索引

  • contains(const T &value) const:检查链表是否包含指定值的元素。
  • count(const T &value) const:返回链表中指定值的元素个数。
  • indexOf(const T &value, int from = 0) const:返回链表中指定值的第一个元素的索引,从位置from开始搜索。如果未找到则返回-1。
  • lastIndexOf(const T &value, int from = -1) const:返回链表中指定值的最后一个元素的索引,从位置from开始搜索。如果from为-1,则从链表末尾开始搜索。如果未找到则返回-1。

6. 迭代器与分割器

  • const_iterator cbegin() const:返回指向链表第一个元素的常量迭代器。
  • const_iterator cend() const:返回指向链表末尾的常量迭代器。
  • reverse_iterator rbegin():返回指向链表最后一个元素的反向迭代器。
  • const_reverse_iterator rbegin() const:返回指向链表最后一个元素的常量反向迭代器。

注意事项

  • QLinkedList中的元素访问(如first()last())在链表为空时可能会导致未定义行为,因此在调用这些函数之前最好先检查链表是否为空。
  • QLinkedList不是线程安全的,如果在多线程环境下使用,需要外部同步机制来保证线程安全。

此外,随着Qt框架的发展,某些接口或特性可能会发生变化,因此建议查阅最新的Qt文档以获取最准确的信息。

3.QLinkedList遍历 

QLinkedList 提供了多种方式来遍历其中的元素。以下是遍历 QLinkedList 的几种常用方法:

1. 使用迭代器

QLinkedList 提供了迭代器和反向迭代器,允许你从头到尾或从尾到头遍历链表。


QLinkedList<int> list;  
list.append(1);  
list.append(2);  
list.append(3);  
  
// 使用迭代器从头到尾遍历  
for (QLinkedList<int>::iterator it = list.begin(); it != list.end(); ++it) {  
    qDebug() << *it;  
}  
  
// 使用反向迭代器从尾到头遍历  
for (QLinkedList<int>::reverse_iterator rit = list.rbegin(); rit != list.rend(); ++rit) {  
    qDebug() << *rit;  
}

2. 使用范围循环(C++11 及以上版本)

如果你使用的是 C++11 或更高版本,你可以使用范围循环来更简洁地遍历 QLinkedList

QLinkedList<int> list = {1, 2, 3};  
  
// 使用范围循环遍历  
for (int value : list) {  
    qDebug() << value;  
}

3. 使用 first() 和 next() 方法

你还可以使用 QLinkedList 提供的 first() 方法来获取链表的第一个元素,并使用 next() 方法来获取下一个元素。这种方法比较底层,需要手动管理迭代过程。

QLinkedList<int> list = {1, 2, 3};  
QList<QLinkedList<int>::Node*> nodes;  
nodes.append(list.first()); // 获取第一个节点的指针  
  
// 遍历节点  
while (!nodes.isEmpty()) {  
    QLinkedList<int>::Node* node = nodes.takeFirst(); // 取出第一个节点并移除  
    qDebug() << node->value; // 访问节点的值  
    if (node->next) {  
        nodes.append(node->next); // 如果有下一个节点,则添加到列表中  
    }  
}

但是,请注意,直接访问 QLinkedList 的内部节点结构(如上面的 Node)通常不是推荐的做法,因为这依赖于 Qt 的内部实现,并且可能会在未来的版本中发生变化。这里只是为了展示一种可能的遍历方法。

4. 使用索引

虽然 QLinkedList 不是一个随机访问容器,但你可以使用索引来遍历链表。不过,这种方法的时间复杂度是 O(n),因为每次访问索引都需要从头开始遍历链表。


QLinkedList<int> list = {1, 2, 3};  
for (int i = 0; i < list.size(); ++i) {  
    qDebug() << list.at(i); // 使用索引访问元素  
}

然而,这种方法并不高效,特别是在链表很长的情况下。通常,更推荐使用迭代器或范围循环来遍历 QLinkedList

注意事项

  • 遍历 QLinkedList 时,请注意不要修改链表的结构(如添加或删除元素),除非你使用的是能够处理这种情况的迭代器(如 STL 中的 std::list 提供的迭代器)。在 Qt 中,直接修改链表可能会导致迭代器失效。
  • 如果你需要在遍历过程中修改链表,可以考虑先收集需要修改的元素的信息,然后在遍历结束后进行修改,或者使用其他数据结构来辅助处理。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值