Detailed explanation of STL container
foreword
(1) As long as it is data, a container must be used. The data in the program is placed in the container for easy addition, deletion, modification and query.
(2) The Qt library provides a set of common template-based container classes (containerclasses). These container classes can be used to store specific types of items ( items ).
(3) Containers can also be nested, such as QMap<QString, QList>, where the type of the key is QString, and the type of the value is QList. It should be noted that there must be a space between the ">>" symbols behind. Otherwise the compiler will treat it as the ">>" operator.
For example: If you need a variable-sized array of type QString, you can use QVector(QString). Compared with the container classes in STL (Standard Template Library, C++'s standard template library), these container classes in Qt are lighter, safer, and easier to use.
The Container Classes (container introduction) (PS: Chinese and English version)
(1)Qt provides the following sequential containers: QList, QLinkedList, QVector, QStack, and QQueue. For most applications, QList is the best type to use. Although it is implemented as an array-list, it provides very fast prepends and appends. If you really need a linked-list, use QLinkedList; if you want your items to occupy consecutive memory locations, use QVector. QStack and QQueue are convenience classes that provide LIFO and FIFO semantics.
(1) Qt provides the following sequential containers: QList, QLinkedList, QVector, QStack and QQueue. For most applications, QList is the best type. Although it is implemented as an array list, it provides very fast prepend and append operations. If you really need a linked list, use QLinkedList; if you want your items to occupy contiguous memory locations, use QVector. QStack and QQueue are convenience classes that provide LIFO and FIFO semantics.
(2)Qt also provides these associative containers: QMap, QMultiMap, QHash, QMultiHash, and QSet. The “Multi” containers conveniently support multiple values associated with a single key. The “Hash” containers provide faster lookup by using a hash function instead of a binary search on a sorted set.
(2) Qt also provides these associative containers: QMap, QMultiMap, QHash, QMultiHash and QSet. "Multi" containers conveniently support multiple values associated with a single key. "Hash" containers provide faster lookups by using a hash function instead of doing a binary search on a sorted set.
(3)As special cases, the QCache and QContiguousCache classes provide efficient hash-lookup of objects in a limited cache storage.
(3) As special cases, the QCache and qcontinuousscache classes provide efficient hash lookup of objects in limited cache storage.
Java style (container and traverser)
container | read-only traverser | read-write traverser |
---|---|---|
QList,QQueue | QListIterator | QMutableListIterator |
QLinkedList | QLinkedListIterator | QMutableLinkedListIterator |
QVector,QStack | QVectorIterator | QMutableVectorIterator |
QSet | QSetIterator | QMutableSetIterator |
QMap<Key, T>,QMultiMap<Key, T> | QMapIterator | QMutableMapIterator |
QHash<Key, T>,QMultiHash<Key, T> | QHashIterator | QMutableHashIterator |
STL style (containers and traversers)
container | read-only traverser | read-write traverser |
---|---|---|
QList,QQueue | QList::const_iterator | QList::iterator |
QLinkedList | QLinkedList::const iterator | QLinkedList::iterator |
QVector,QStack | QVector::const iterator | QVector::iterator |
QSet | QSet::const iterator | QSet::iterator |
QMap<Key, T>,QMultiMap<Key, T> | QMap<Key, T>::const_iterator | QMap<Key, T>::iterator |
QHash<Key, T>,QMultiHash<Key, T> | QHash<Key, T>::const_iterator | QHash<Key, T>::iterator |
(1) STL-style iterators are compatible with Qt and STL's generic algorithms (generic algorithms), and are optimized for speed. For each container class, there are two STL-style iterator types: one provides read-only access, and the other provides read-write access. Because read-only iterators are much faster than read-write iterators, read-only iterators should be used whenever possible.
(2) The API of the STL-style iterator imitates the pointer of the array, for example, use the "++" operator to move the iterator back to point to the next item; use the "*" operator to return the item pointed to by the iterator, etc. . It should be noted that, unlike Java-style iterators, STL-style iterators point directly to items. The begin() function of one of the containers returns an iterator pointing to the first item in the container, and the end() function also returns an iterator, but this iterator points to the imaginary virtual space next to the last item in the container. item, end() marks an invalid position, and the begin() function is equivalent to the end() function when the list is empty.
QList (linked list)
QList is a template class which provides a list.
QList is actually a pointer array of T-type items, so it supports index-based access,
and when the number of items is less than 1000, it can implement fast insertion in the middle of the list.
QList provides many convenient interface functions to manipulate the items in the list, for example:
(1) Insert operation insert();
(2) Replacement operation replace();
(3) Remove operation removeAt();
(4) Mobile operation move();
(5) Exchange operation swap();
(6) Add item append() at the end of the table;
(7) Add item prepend() in the table header;
(8) Remove the first item removeFirst();
(9) Remove the last item removeLast();
(10) Remove an item from the list and get the item takeAt(); //Get the specified item
(11) There are also corresponding takeFirst() and takeLast(); //Get "the first item" and "get the last item"
(12) Get the index indexOf() of an item;
(13) Determine whether the corresponding item contains();
(14) Obtain count() of the number of occurrences of an item;
For QList, you can use the "<<" operator to insert items into the list, for example: "List << 1 << 3 << 5;" You
can also use the "[]" operator to access an item through an index, where the item are numbered starting from 0.
However, for read-only access, another method is to use the at() function, which is much faster than the "[]" operator.
Reference source code:
#include "qcontainerclasses.h"
#include <QtWidgets/QApplication>
#include <QDebug>
#include <iostream>
#include <QLinkedList>
using namespace std;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QContainerClasses w;
//w.show();
#if 0
QList<int> qList;
for (int i = 0; i < 10; i++)//插入十个数字
{
qList.append(i); //往后追加
}
qList.prepend(100); //往前追加一个数字100
qDebug() << QString::fromLocal8Bit("原始数据:") << qList;
qDebug() << "************************************************************************";
/* 方法1: for循环遍历 */
qDebug() << QString::fromLocal8Bit("方法1:");
for (int i = 0; i < qList.size(); i++)
{
qDebug() << qList.at(i);//用qList.at()获取位置
qDebug() << qList[i];//取qList[]下标获取位置
}
qDebug() << "************************************************************************";
/* 方法2: foreach
按顺序遍历容器中的所有项,可以使用Qt的foreach关键字。
foreach是对c++语言添加的特定于qt的内容,并使用预处理器实现。
*/
qDebug() << QString::fromLocal8Bit("方法2:");
foreach(int itm, qList)
{
qDebug() << itm; // 结果为A,B,C
}
qDebug() << "************************************************************************";
/* 方法3.1: Java风格迭代器 只读迭代器 */
qDebug() << QString::fromLocal8Bit("方法3:");
QListIterator<int> it(qList); //只读迭代器
while (it.hasNext())//判断是否一直有下一个,直到没有结束
{
qDebug() << it.next();
}
qDebug() << "************************************************************************";
/* 方法3.2: Java风格迭代器 读写迭代器 */
qDebug() << QString::fromLocal8Bit("方法4:");
QMutableListIterator<int> mit(qList); //只读迭代器
while (mit.hasNext())//和上面一样
{
if (mit.next() == 8)//判断是否是第8个嘛,修改值为66
mit.setValue(66);
}
qDebug() << "************************************************************************";
/* 方法4.1: STL风格迭代器 只读迭代器 */
qDebug() << QString::fromLocal8Bit("方法5:");
QList<int>::const_iterator itm;//常迭代器
for (itm = qList.begin(); itm != qList.end(); ++itm)
{
qDebug() << (*itm);//指针遍历打印
}
qDebug() << "************************************************************************";
/* 方法4.1: STL风格迭代器 读写迭代器 */
qDebug() << QString::fromLocal8Bit("方法6:");
QList<int>::iterator itm2;//迭代器
for (itm2 = qList.begin(); itm2 != qList.end(); ++itm2)
{
qDebug() << (*itm2);//指针遍历打印
*itm2 = (*itm2) * 6;//取值->*6赋值回去(PS:本轮不会修改,第二遍遍历值将改变)
}
qDebug() << "************************************************************************";
qDebug() << QString::fromLocal8Bit("方法7");
QList<int>::iterator itm3;//迭代器
for (auto itm3 : qList)//
{
qDebug() << itm3;
}
#endif//QList介绍及其操作
#if 0
//QLinkedList:基于迭代器访问的List,方便快速插入、删除
QLinkedList<int> List;
List << 1 << 3 << 5;//可以用此方法赋值进链表中
foreach(int i, List)//foreach是Qt独有的遍历方法
{
qDebug() << i;
}
#endif//QLinkedList介绍及其遍历方法
return a.exec();
}
QVector (variable array)
Detailed reference: vector notes c++
QMap (key-value pair)
STL version reference: map mapping
The QMap class is a container class that provides a skiplist based dictionary.
QMap is one of Qt's general-purpose container classes, which store (key, value) pairs and provide fast lookup of the value associated with the key.
QMap provides many convenient interface functions,
such as:
(1) insert operation insert();
(2) Get the value value();
(3) Whether to include a key contains();
(4) delete a key remove();
(5) Delete a key and get the value corresponding to the key take();
(6) Empty operation clear();
(7) Insert one-key multi-value insertMulti().
You can use the "[]" operator to insert a key-value pair or get the value of a key, but when using this operator to get the value of a key that does not exist, the key will be inserted into the map by default. To avoid this situation
, You can use the value() function to get the value of a key. When using the value() function, if the specified key does not exist, it will return 0 by default. You can
provide parameters when using this function to change the value returned by default.
QMap defaults to one key corresponding to one value, but you can also use insertMulti() to insert one key and multiple values. For the case of one key and multiple values, it is more convenient to use QMultiMap, a subclass of QMap
.
Reference source code:
#include "qcontainerclasses.h"
#include <QtWidgets/QApplication>
#include <QDebug>
#include <iostream>
#include <QLinkedList>
using namespace std;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QContainerClasses w;
//w.show();
#if 0
QMap<QString, int> map;//构造一个QMap
//赋值方法
map["one"] = 1; // 向map中插入("one",1)
map["three"] = 3;// 向map中插入("three",3)
map.insert("seven", 7); // 使用insert()函数进行插入("seven",7)
//获取键的值,使用"[]"操作符时,如果map中没有该键,那么会自动插入key
qDebug() << "========================================================";
int value1 = map["six"];
qDebug() << "value1:" << value1;
qDebug() << "contains 'six ' ?" << map.contains("six");//检查是否包含six这个key,有则为true,无则为false
// 使用value()函数获取键的值,这样当键不存在时不会自动插入
qDebug() << "========================================================";
int value2 = map.value("five");//获取map的值
qDebug() << "value2:" << value2;//value2默认返回0
qDebug() << "contains 'five ' ?" << map.contains("five");//返回为false
// 当键不存在时,value()默认返回0。当设定了键值后不论有没有这个"key()"或者"value()"会自动插入key
qDebug() << "========================================================";
int value3 = map.value("nine", 9);//没有则插入一个键值
qDebug() << "value3:" << value3;//value3默认返回9
#endif //map赋值操作
#if 0
QMap<int, QString> Employees;//构建一个QMap
//插入数据
Employees.insert(1, "Bob");
Employees.insert(2, "Chad");
Employees.insert(3, "Mary");
Employees.insert(4, "oldWang");
Employees[5] = "Danny"; //不推荐这样赋值,很难分清是下标位置还是key
QMap<int, QString>::const_iterator i = Employees.constBegin();//构造一个const_iterator常迭代器
while (i != Employees.constEnd()) //循环遍历
{
cout << i.key() << ": " << i.value().toStdString() << endl;
++i;
}
cout << "==============================================================="<< endl;
QMap<int, QString>::iterator j = Employees.begin();//构造一个iterator迭代器
for (j; j != Employees.end(); j++)//循环遍历
{
//搜索帮助文档:T &iterator::value() const
/*
例子:
if (i.key() == "Hello")
i.value() = "Bonjour";
*/
if (j.value()=="oldWang")
{
j.value() = "robort";//修改value
}
cout << j.key() << ":" << j.value().toStdString()<<endl;//打印
}
#endif //QMap遍历修改value操作
return a.exec();
}
QHash (hash algorithm)
What is a hash algorithm reference: what is a hash (hash)
The difference between QMap and QHash:
(1) QHash has a faster search speed than QMap
(2) QHash stores data items in any order, while QMap always stores data in key order
(3) The key type Key of QHash must provide operator==() and a global qHash(Key) function, while the key type Key of QMap must provide the operator<() function.
Reference source code:
#include "qcontainerclasses.h"
#include <QtWidgets/QApplication>
#include <QDebug>
#include <iostream>
#include <QLinkedList>
using namespace std;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QContainerClasses w;
//w.show();
#if 0
QHash<int, QString> Employees;//构造一个哈希键值,是随机存储的。
//插入键值
Employees.insert(1, "Bob");
Employees.insert(2, "Chad");
Employees.insert(3, "Mary");
//遍历Hash的key
foreach(int i, Employees.keys())
{
qDebug() << Employees[i];//遍历输出值,是随机出现的。
}
QHashIterator<int, QString>Iter(Employees);//构造一个Hash迭代器继承Employees哈希键值
while (Iter.hasNext())//判断是否还有Employees数据
{
Iter.next();//输出下一个数据(PS:必须要有这个,不然会触发中断)
qDebug() << Iter.key() << " = " << Iter.value();//打印数据
}
#endif //哈希算法
return a.exec();
}
Commonly used algorithms (the following content is source code, no introduction)
qsort (sort)
#include "qcontainerclasses.h"
#include <QtWidgets/QApplication>
#include <QDebug>
#include <iostream>
#include <QLinkedList>
using namespace std;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QContainerClasses w;
//w.show();
#if 1
QList<int> list;
list << 36 << 16 << 66 << 6 << 56;
qSort(list.begin(), list.end());//正序排序
qDebug() << QString::fromLocal8Bit("正序排序:") << endl << list;
qSort(list.end(), list.begin(),qGreater<int>());//倒序排序
qDebug() << QString::fromLocal8Bit("倒序排序:") << endl << list;
#endif //qSort(快速排序)
return a.exec();
}
qcopy (copy)
#include "qcontainerclasses.h"
#include <QtWidgets/QApplication>
#include <QDebug>
#include <iostream>
#include <QLinkedList>
using namespace std;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QContainerClasses w;
//w.show();
#if 0
/*****************************************************************/
//基本操作
QStringList list;//构造一个QString链表
list << "a" << "b" << "c";//赋值到list中
QVector<QString> vect(3);//构造一个QVector
//OutputIterator qCopy(InputIterator begin, InputIterator end, OutputIterator dest)
qCopy(list.begin(), list.end(), vect.begin());//将list链表中的数据qCopy到vect中;
foreach(QString item, vect)//遍历QVector
{
qDebug() << item;
}
/*****************************************************************/
cout << "=====================分界线1======================" << endl;
//扩展内容:
QStringList list2;//构造一个QStringList
list2 << "one" << "two" << "three";//赋值三个值到list
QVector<QString> vect1(3);//构造一个QVector
qCopy(list2.begin(), list2.end(), vect1.begin());//将list2链表中的数据qCopy到vect1中;
QVector<QString>::iterator j;//创建一个迭代器
for (auto j : vect1)//遍历vect1
{
qDebug() << j;//打印数据
}
cout << "=====================分界线2======================" << endl;
QVector<QString> vect2(8);//构造一个QVector,给定8个数组大小
//"vect2.begin() + 2"是指距离隔两个数组大小进行qCopy
qCopy(list2.begin(), list2.end(), vect2.begin() + 2);//将list2链表中的数据qCopy到vect2中
QVector<QString>::iterator i;//创建一个迭代器
for (auto i : vect2)//遍历vect2
{
qDebug() << i;//打印数据
}
#endif//qCopy(复制)
return a.exec();
}
qFill (fill a container with a specific value)
#include "qcontainerclasses.h"
#include <QtWidgets/QApplication>
#include <QDebug>
#include <iostream>
#include <QLinkedList>
using namespace std;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QContainerClasses w;
//w.show();
#if 0
QVector<QString> vect(5);//构造一个QVector,5个数组大小
//void qFill(ForwardIterator first, ForwardIterator last, const T &val)
//从下标位置1到end()前两个结束,将"PUBG"赋值进去
qFill(vect.begin() + 1, vect.end()-2, "PUBG");
foreach(QString item, vect)//遍历vect
{
qDebug() << item;//打印数据
}
#endif//qFill()用特定的值填充容器
return a.exec();
}
qfind (find)
#include "qcontainerclasses.h"
#include <QtWidgets/QApplication>
#include <QDebug>
#include <iostream>
#include <QLinkedList>
using namespace std;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QContainerClasses w;
//w.show();
#if 0
/*******************************************************************************/
//Qlist使用qfind
QList<int> List;//构造一个QList
List << 1 << 5 << 15 << 25;//赋值到List中
//InputIterator qFind(InputIterator first, InputIterator last, const T &val)
//InputIterator qFind(从List开头,到List结尾,查找值)
QList<int>::const_iterator Iter = qFind(List.begin(), List.end(), 25);
if (Iter != List.end())//判断是否查询到了结尾处
{
qDebug() << "Find: " << *Iter;//打印查找到的数据
}
else
{
qDebug() << "Not Find";//查找失败
}
/*******************************************************************************/
cout << "=====================分界线1======================" << endl;
//QMap使用qfind
QMap<QString, QString> Employees;//构造一个QMap,(会自动对key进行排序)
//给QMap赋键值
Employees.insert("c++", "Bob");
Employees.insert("win32", "xiaqi");
Employees.insert("mfc", "laowang");
Employees.insert("qt", "mengfan");
Employees["linux"] = "Danny";
/* Danny 变laowang */
//用iterator查找key: find("linux");
QMap<QString, QString>::iterator i = Employees.find("linux");
while (i != Employees.end() && i.key() == "linux")//判断是否查找到结尾并且key值为"linux";
{
qDebug() << i.key() << i.value();//打印原数据
i.value() = "oldwang";//更换value值
++i;
}
cout << "=====================分界线2======================" << endl;
/* 再遍历一次 */
i = Employees.begin();//重新给iterator赋值到开头位置
while (i != Employees.end())//判断是否为结尾处
{
qDebug() << i.key() << i.value();//打印更新后数据
++i;
}
#endif
return a.exec();
}