Qt 容器类详解:顺序容器与关联容器及其遍历方法
在 Qt 开发中,容器类(Container Classes)是存储和管理数据的重要工具。Qt 提供了多种容器类,包括顺序容器(Sequential Containers)和关联容器(Associative Containers),它们分别适用于不同的场景。本文将详细介绍 Qt 中的顺序容器和关联容器,并讲解如何遍历这些容器。
一、顺序容器类(Sequential Containers)
顺序容器类用于按顺序存储和访问数据。Qt 提供了三种主要的顺序容器:QList
、QStack
和 QQueue
。
1. QList
:动态数组
QList
是一个动态数组,支持随机访问和高效的插入/删除操作。
特点:
- 支持在任意位置插入和删除元素。
- 提供
append()
、prepend()
、insert()
等方法。 - 允许使用
[]
运算符进行随机访问。
示例代码:
QList<int> list;
list.append(1); // 添加元素
list.prepend(0); // 插入到开头
int first = list[0]; // 随机访问
2. QStack
:先进后出(LIFO)
QStack
是基于 QList
实现的先进后出(LIFO)容器。
特点:
- 提供
push()
(入栈)、pop()
(出栈)和peek()
(查看栈顶)方法。 - 支持
isEmpty()
和size()
等常用操作。
示例代码:
QStack<int> stack;
stack.push(1); // 入栈
stack.push(2);
int top = stack.peek(); // 查看栈顶
stack.pop(); // 出栈
3. QQueue
:先进先出(FIFO)
QQueue
是基于 QList
实现的先进先出(FIFO)容器。
特点:
- 提供
enqueue()
(入队)、dequeue()
(出队)和isEmpty()
等方法。 - 支持
front()
和back()
查看队列的首尾元素。
示例代码:
QQueue<int> queue;
queue.enqueue(1); // 入队
queue.enqueue(2);
int front = queue.front(); // 查看队首
queue.dequeue(); // 出队
二、关联容器类(Associative Containers)
关联容器类用于通过键快速查找数据。Qt 提供了四种主要的关联容器:QMap
、QMultiMap
、QHash
和 QMultiHash
。
1. QMap
:有序键值对容器
QMap
是基于红黑树实现的有序键值对容器,键是有序的。
特点:
- 支持
insert()
、remove()
、contains()
等操作。 - 提供
begin()
、end()
迭代器,支持按顺序遍历。
示例代码:
QMap<QString, int> map;
map.insert("apple", 1); // 插入键值对
map.insert("banana", 2);
int value = map["apple"]; // 访问值
2. QMultiMap
:允许重复键的有序容器
QMultiMap
是允许键重复的有序容器,基于 QMap
实现。
特点:
- 支持插入重复键。
- 提供
count()
方法统计某个键的出现次数。
示例代码:
QMultiMap<QString, int> multiMap;
multiMap.insert("fruit", 1);
multiMap.insert("fruit", 2);
int count = multiMap.count("fruit"); // 计数
3. QHash
:无序键值对容器
QHash
是基于哈希表实现的无序键值对容器,插入和查找操作时间复杂度为 O(1)。
特点:
- 提供
insert()
、remove()
、contains()
等操作。 - 支持
begin()
、end()
迭代器,但遍历顺序无序。
示例代码:
QHash<QString, int> hash;
hash.insert("apple", 1); // 插入键值对
hash.insert("banana", 2);
int value = hash["apple"]; // 访问值
4. QMultiHash
:允许重复键的无序容器
QMultiHash
是允许键重复的无序容器,基于 QHash
实现。
特点:
- 支持插入重复键。
- 提供
count()
方法统计某个键的出现次数。
示例代码:
QMultiHash<QString, int> multiHash;
multiHash.insert("fruit", 1);
multiHash.insert("fruit", 2);
int count = multiHash.count("fruit"); // 计数
三、遍历容器类
1. 顺序容器遍历
QList
遍历:
QList<int> list = {1, 2, 3, 4};
// 迭代器遍历
for (QList<int>::const_iterator it = list.begin(); it != list.end(); ++it) {qDebug() << *it;
}
// foreach 循环
foreach (int value, list) {qDebug() << value;
}
QStack
遍历:
QStack<int> stack;
stack.push(1);
stack.push(2);
stack.push(3);
// 迭代器遍历
for (QStack<int>::const_iterator it = stack.begin(); it != stack.end(); ++it) {qDebug() << *it;
}
// foreach 循环
foreach (int value, stack) {qDebug() << value;
}
QQueue
遍历:
QQueue<int> queue;
queue.enqueue(1);
queue.enqueue(2);
queue.enqueue(3);
// 迭代器遍历
for (QQueue<int>::const_iterator it = queue.begin(); it != queue.end(); ++it) {qDebug() << *it;
}
// foreach 循环
foreach (int value, queue) {qDebug() << value;
}
2. 关联容器遍历
QMap
遍历:
QMap<QString, int> map;
map.insert("apple", 1);
map.insert("banana", 2);
// 迭代器遍历键值对
for (QMap<QString, int>::const_iterator it = map.begin(); it != map.end(); ++it) {qDebug() << "Key: " << it.key() << ", Value: " << it.value();
}
// 遍历键
foreach (QString key, map.keys()) {qDebug() << "Key: " << key << ", Value: " << map.value(key);
}
QMultiMap
遍历:
QMultiMap<QString, int> multiMap;
multiMap.insert("fruit", 1);
multiMap.insert("fruit", 2);
// 迭代器遍历键值对
for (QMultiMap<QString, int>::const_iterator it = multiMap.begin(); it != multiMap.end(); ++it) {qDebug() << "Key: " << it.key() << ", Value: " << it.value();
}
// 遍历键
foreach (QString key, multiMap.keys()) {foreach (int value, multiMap.values(key)) {qDebug() << "Key: " << key << ", Value: " << value;}
}
QHash
遍历:
QHash<QString, int> hash;
hash.insert("apple", 1);
hash.insert("banana", 2);
// 迭代器遍历键值对
for (QHash<QString, int>::const_iterator it = hash.begin(); it != hash.end(); ++it) {qDebug() << "Key: " << it.key() << ", Value: " << it.value();
}
// foreach 循环遍历键
foreach (QString key, hash.keys()) {qDebug() << "Key: " << key << ", Value: " << hash.value(key);
}
QMultiHash
遍历:
QMultiHash<QString, int> multiHash;
multiHash.insert("fruit", 1);
multiHash.insert("fruit", 2);
// 迭代器遍历键值对
for (QMultiHash<QString, int>::const_iterator it = multiHash.begin(); it != multiHash.end(); ++it) {qDebug() << "Key: " << it.key() << ", Value: " << it.value();
}
// 遍历键
foreach (QString key, multiHash.keys()) {foreach (int value, multiHash.values(key)) {qDebug() << "Key: " << key << ", Value: " << value;}
}
四、总结
- 顺序容器(如
QList
、QStack
、QQueue
)适用于按顺序存储和访问数据的场景,支持高效的插入和删除操作。 - 关联容器(如
QMap
、QMultiMap
、QHash
、QMultiHash
)适用于需要通过键快速查找数据的场景,支持键值对的存储和管理。
选择合适的容器类型可以显著提高代码的效率和可维护性。希望本文能够帮助你更好地理解和使用 Qt 的容器类!