Qt - 容器与算法

QTL与STL的区别

QTL和STL对比,两容器之间的对应关系。

 

API上的差别

  • QTL有Qt风格和STL风格,两种风格的API,比如 append() 和push_back()count() 和 size()isEmpty() 和empty()
  • QTL不支持allocator;STL支持指定allocator以及自定义allocator。
  • Qt除了我们常用的类似于STL的迭代器,也提供了JAVA风格的迭代器。关联容器,Qt STL风格迭代器通过iterator.key()iterator.value()获取键值,STL通过std::pair<key,value>结构获取键值。

实现原理上的差别

  • QTL采用隐式共享,赋值操作执行的都是浅拷贝。STL,所有STL容器赋值操作执行的都是深拷贝;
  • QTL线程安全,STL线程不安全;
  • QQueueQList作为底层容器,QStackQVector作为底层容器;std::queuestd::stack都默认采用 std::deque作为底层容器,可以手动指定容器。

QTL简要介绍

  • 除了QVarLengthArray,所有QTL数据都存放在堆空间,支持隐式共享。
  • QVarLengthArray:数据存储在对象内,连续存储结构,无隐式共享功能;
  • QVector:在堆空间存储数据,连续存储结构;
  • QLinkedList:双向链表,在堆空间存储数据,链式存储结构;
  • QList:后面详细说明;
  • QMap:用红黑树管理键值对数据,key不可重复;
  • QMultiMap:用红黑树管理键值对数据,key可重复;
  • QHash:用哈希表管理键值对数据,key不可重复;
  • QMultiHash:用哈希表管理键值对数据,key可重复;
  • QSet:用哈希表存储值类型的数据,值可重复;
  • QQueue:队列结构,先进先出;
  • QStack:栈结构,先进后出;

 

1. 迭代器

Qt提供了两种遍历容器的风格:

java风格的迭代器和stl风格的迭代器。java风格的迭代器更容易使用并提供高级功能,而STL风格的迭代器稍微更高效,可以与Qt和STL的通用算法一起使用。

  • java风格

容器 只读迭代器 读写迭代器
QList<T>,QQueue<T> QListIterator<T> QMutableListIterator<T>
QLinkedList<T> QLinkedListIterator<T> QMutableLinkedListIterator<T>
QVector<T>,QStack<T> QVectorIterator<T> QMutableVectorIterator<T>
QSet<T> QSetIterator<T> QMutableSetIterator<T>
QMap<Key,T>,QMultiMap<Key,T> QMapIterator<T> QMutableMapIterator<T>
QHash<Key,T>,QMultiHash<Key,T> QHashIterator<T> QMutableHashIterator<T>
  • STL风格

容器 只读迭代器 读写迭代器
QList<T>,QQueue<T> QList<T>::const_iterator QList<T>::iterator
QLinkedList<T> QLinkedList<T>::const_iterator QLinkedList<T>::iterator
QVector<T>,QStack<T> QVector<T>::const_iterator QVector<T>::iterator
QSet<T> QSet<T>::const_iterator QSet<T>::iterator
QMap<Key,T>,QMultiMap<Key,T> QMap<T>::const_iterator QMap<T>::iterator
QHash<Key,T>,QMultiHash<Key,T> QHash<T>::const_iterator QHash<T>::iterator

 

示例代码:

//java风格迭代器
QList<int> list;
list<<1<<2<<3<<4<<5;
QListIterator<int> it(list);
while (it.hasNext())
{
    qDebug()<<it.next();
}


//STL风格迭代器
QList<int> list2 = {1,2,3,4,5};
QList<int>::iterator it;//定义一个读写迭代器
for(it = list2.begin(); it != list2.end(); it++)
{
    qDebug()<<*it;
}

 

 

2. 容器

Qt中提供了一组通用的基于模板的容器类(container class)。可以用来存储指定的项(items),与STL(C++标准模板库)相比,Qt中的容器更轻量,更安全,功能更强大。

  • 序列式容器

    • QList

    • QLinkedList

    • QVector

    • QStack

    • QQueue

    对于大多数应用程序,QList是最好的类型。虽然它是作为数组列表实现的,但是它提供了非常快的前置和附加。如果你真的需要一个链表,使用QLinkedList;如果您希望您的项目占用连续的内存位置,请使用QVector。QStack和QQueue是提供LIFO和FIFO语义的便利类。

  • 关联式容器

    • QMap

    • QMultiMap

    • QHash

    • QMultiHash

    • QSet

    “multi”容器方便地支持与单个键相关联的多个值。“hash”容器通过使用哈希函数而不是对排序集进行二进制搜索,从而提供更快的查找。

  • 作为特殊情况,QCache和QContiguousCache类在有限的缓存存储中提供了对象的高效散列查找。

 

2.1 序列式容器

2.1.1 QList

QList模板提供了一个列表,实际上是一个指针数组,当项目数小于1000时,可以实现快速的插入删除操作

 

QList<T> 是 Qt 的通用容器类之一。它将项目存储在一个列表中,该列表提供基于索引的快速访问和基于索引的插入和删除。 QList<T>、QLinkedList<T> 和 QVector<T> 提供类似的 API 和功能。它们通常可以互换,但会产生性能后果。

使用概述:

  • QVector 应该是您的默认首选。 QVector<T> 通常会比 QList<T> 提供更好的性能,因为 QVector<T> 总是将其项按顺序存储在内存中,其中 QList<T> 将在堆上分配它的项,除非 sizeof(T) <= sizeof(void *) 并且 T 已使用 Q_DECLARE_TYPEINFO 声明为 Q_MOVABLE_TYPE 或 Q_PRIMITIVE_TYPE。

  • 然而,QList 在整个 Qt API 被大量使用,用于传递参数和返回值。 使用 QList可以很方便的与这些 API 进行交互。

  • 如果您需要一个真正的链表,它保证常量时间内插入列表,并且使用迭代器指向项而不是索引,那么请使用QLinkedList。

公有函数

  • 添加数据

//支持流插入
QList<int>()<<1<<2<<3<<4<<5;
​
void append(const T &value)
void append(const QList<T> &value)
 
void insert(int i, const T &value)
QList::iterator insert(QList::iterator before, const T &value)
​
void prepend(const T &value)
void push_back(const T &value)
void push_front(const T &value)
  • 获取数据

T &back()
const T &back() const  
​
T &first()
const T &first() const
T &front()
const T &front() const 
​
T &last()
const T &last() const 
​
const T &constFirst() const
const T &constLast() const
​
//返回下标为i的元素,如果下标i不合法,则返回defaultValue
T value(int i) const
T value(int i, const T &defaultValue) const  
    
const T &at(int i) const
T &operator[](int i)
const T &operator[](int i) const
//返回从位置pos开始的子列表。如果length为-1(默认),则包含pos中的所有元素; 
QList<T> mid(int pos, int length = -1) const
  • 删除数据

void clear()
    
QList::iterator erase(QList::iterator pos)
QList::iterator erase(QList::iterator begin, QList::iterator end)   
​
void pop_back()
void pop_front()
//删除元素   
int removeAll(const T &value)
bool removeOne(const T &value)
void removeAt(int i)
void removeFirst()
void removeLast()
//删除元素并返回它,如果不使用返回值,removeAt()会更高效 
T takeAt(int i)
T takeFirst()
T takeLast()
  • 查找/替换

//返回value在列表中第一次出现的索引位置,从索引位置from向前搜索。 如果没有匹配的项,则返回-1。  
int indexOf(const T &value, int from = 0) const
//返回value在列表中最后一次出现的索引位置,从索引位置from反向搜索。如果from是-1(默认值),则搜索从最后一项开始。如果没有匹配的项,则返回-1。     
int lastIndexOf(const T &value, int from = -1) const
//将索引位置为i的项替换为value
void replace(int i, const T &value)
//如果列表中包含值的出现,则返回true; 否则返回false。 该函数要求值类型具有operator==()的实现。     
bool contains(const T &value) const
  • 交换/移动

//将索引位置from到索引位置to  
//["A", "B", "C", "D", "E", "F"] move(1,4)-> ["A", "C", "D", "E", "B", "F"]
void move(int from, int to)
​
void swap(QList<T> &other)
//交换下标i j的元素    
void swapItemsAt(int i, int j)
  • 判断函数

int count(const T &value) const
int count() const
int size() const
int length() const
​
bool empty() const
bool isEmpty() const
//如果列表第一项/后一项等于value,则返回true; 否则返回false。  
bool startsWith(const T &value) const    
bool endsWith(const T &value) const
//预分配空间大小    
void reserve(int alloc)
  • 和其他容器互转

QSet<T> toSet() const
std::list<T> toStdList() const
QVector<T> toVector() const
​
[static] QList<T> fromSet(const QSet<T> &set)
[static] QList<T> fromStdList(const std::list<T> &list)
[static] QList<T> fromVector(const QVector<T> &vector)

 

2.1.2 QStringList

QStringList继承自QList<QString>。 它提供基于索引的快速访问以及快速插入和删除。 将字符串列表作为值参数传递既快速又安全。 QList的所有功能也适用于QStringList。 例如,可以使用isEmpty()来测试列表是否为空,还可以调用append()、prepend()、insert()、replace()、removeAll()、removeAt()、removeFirst()、removeLast()和removeOne()等函数来修改QStringList。 此外,QStringList提供了一些方便的函数,使处理字符串列表更容易:

  • 判断是否包含某个字符串

bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
bool contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
bool contains(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
  • 过滤:返回包含子字符串str的所有字符串的列表

QStringList filter(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
QStringList filter(QStringView str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
QStringList filter(const QRegExp &rx) const
QStringList filter(const QRegularExpression &re) const
  • 查找

//从左往右查找
int indexOf(const QRegExp &rx, int from = 0) const
int indexOf(QStringView str, int from = 0) const
int indexOf(QLatin1String str, int from = 0) const
int indexOf(QRegExp &rx, int from = 0) const
int indexOf(const QRegularExpression &re, int from = 0) const
    
//从右往左查找    
int lastIndexOf(const QRegExp &rx, int from = -1) const
int lastIndexOf(QStringView str, int from = -1) const
int lastIndexOf(QLatin1String str, int from = -1) const
int lastIndexOf(QRegExp &rx, int from = -1) const
int lastIndexOf(const QRegularExpression &re, int from = -1) const
  • 连接:将QStringList中的所有字符串连接为一个字符串,每个元素由给定的分隔符(可以是空串)分隔。

//支持流插入 <<
QString join(const QString &separator) const
QString join(QStringView separator) const
QString join(QLatin1String separator) const
QString join(QChar separator) const
  • 删除:从QStringList中删除重复的元素。 返回已删除元素的数量。

int removeDuplicates()
  • 替换:返回一个字符串列表,其中每个字符串在找到before文本时都将before文本替换为after文本

QStringList &replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
QStringList &replaceInStrings(QStringView before, QStringView after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
QStringList &replaceInStrings(const QString &before, QStringView after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
QStringList &replaceInStrings(QStringView before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive)
QStringList &replaceInStrings(const QRegExp &rx, const QString &after)
QStringList &replaceInStrings(const QRegularExpression &re, const QString &after)
  • 排序:升序

void sort(Qt::CaseSensitivity cs = Qt::CaseSensitive)

 

2.1.3 QLinkedList

单链表

 

2.1.4 QVector

//返回vector底层数组指针。只要不重新分配vector对象,指针就保持有效。 这个函数在将vector传递给接受普通c++数组的函数时非常有用。    
T *data()
const T *data() const
//将value赋给向量中的所有项。 如果size不同于-1(默认值),则vector的大小将被调整为size之前的大小。
QVector<T> &fill(const T &value, int size = -1)

 

2.1.5 QStack

T pop()
void push(const T &t)
void swap(QStack<T> &other)
T &top()
const T &top() const

 

2.1.6 QQueue

//删除队头并返回它  
T dequeue()
//将值t加到队尾    
void enqueue(const T &t)
//返回队头的引用
T &head()
const T &head() const
    
void swap(QQueue<T> &other)

 

2.2 关联式容器

2.2.1 QMap

QMap<Key, T> 是 Qt 的通用容器类之一。 它存储(键,值)对,并提供与键关联的值的快速查找。 QMap 和 QHash 提供非常相似的功能。 区别在于:

  • QHash 提供比 QMap 更快的平均查找速度。

  • 在迭代 QHash 时,项目是任意排序的。 使用 QMap,项目总是按键排序。

  • QHash 的键类型必须提供 operator==() 和全局 qHash(Key) 函数。 QMap 的键类型必须提供 operator<() 指定总顺序。 从 Qt 5.8.1 开始,使用指针类型作为键也是安全的,即使底层 operator<() 不提供全序。

公有函数

  • 添加数据

//插入新的键值对,如果已经有一个键为key的项,则该项的值将被value替换;如果有多个键为key的项,则最近插入的项的值将被value替换。  
QMap::iterator insert(const Key &key, const T &value)
QMap::iterator insert(QMap::const_iterator pos, const Key &key, const T &value)
//插入新的键值对,如果在map中已经有一个具有相同键的项,这个函数将创建一个新的项    
QMap::iterator insertMulti(const Key &key, const T &value)
QMap::iterator insertMulti(QMap::const_iterator pos, const Key &key, const T &value)
  • 获取数据

T &first()
const T &first() const
const Key &firstKey() const
    
const Key key(const T &value, const Key &defaultKey = Key()) const 

QList<Key> keys() const
QList<Key> keys(const T &value) const
T &last()
const T &last() const
const Key &lastKey() const

//返回一个列表,该列表包含映射中的所有键。 在映射中出现多次的键在返回的列表中只出现一次。      
QList<Key> uniqueKeys() const
//将其他map中的所有项目插入到该map中。      
QMap<Key, T> &unite(const QMap<Key, T> &other)

const T value(const Key &key, const T &defaultValue = T()) const
QList<T> values() const
QList<T> values(const Key &key) const

T &operator[](const Key &key)
const T operator[](const Key &key) const
  • 删除数据

void clear()

QMap::iterator erase(QMap::iterator pos)

int remove(const Key &key)
    
T take(const Key &key)
  • 查找

bool contains(const Key &key) const
/* 返回两个迭代器
迭代器1:是指向当前 map 容器中第一个大于或等于 key 的键值对的迭代器(lowerBound())。
迭代器2:是指向当前 map 容器中第一个大于 key 的键值对的迭代器。(upperBound())
*/
QPair<QMap::iterator, QMap::iterator> equal_range(const Key &key)
QPair<QMap::const_iterator, QMap::const_iterator> equal_range(const Key &key) const
    
QMap::iterator find(const Key &key)
QMap::const_iterator find(const Key &key) const
    
QMap::iterator lowerBound(const Key &key)
QMap::const_iterator lowerBound(const Key &key) const

QMap::iterator upperBound(const Key &key)
QMap::const_iterator upperBound(const Key &key) const
  • 判断

int count(const Key &key) const
int count() const
int size() const
    
bool empty() const
bool isEmpty() const
  • 遍历
QMap<QString, int> map;

QMap<QString, int>::iterator it;
for (it = map.begin(); it != map.end(); ++it) 
{
    qDebug() << "Key:" << it.key() << "Value:" << it.value();
}

 

2.2.2 QMultiMap

  • 插入和替换:插入新的键值对。

    • 如果已经有一个键为key的项,则该项的值将被value替换。

    • 如果有多个键为key的项,则最近插入的项的值将被value替换。

typename QMap<Key, T>::iterator replace(const Key &key, const T &value)

 

2.2.3 QHash

  • 添加数据

QHash::iterator insert(const Key &key, const T &value)
QHash::iterator insertMulti(const Key &key, const T &value)
  • 获取数据

const Key key(const T &value) const
const Key key(const T &value, const Key &defaultKey) const

QList<Key> keys() const
QList<Key> keys(const T &value) const
   
QList<Key> uniqueKeys() const
QHash<K, V> &unite(const QHash<K, V> &other)
const T value(const Key &key) const
const T value(const Key &key, const T &defaultValue) const
QList<T> values() const
QList<T> values(const Key &key) const
  • 删除数据

void clear()

QHash::iterator erase(QHash::const_iterator pos)
QHash::iterator erase(QHash::iterator pos)
    
QPair<QHash::iterator, QHash::iterator> equal_range(const Key &key)
QPair<QHash::const_iterator, QHash::const_iterator> equal_range(const Key &key) const
   
int remove(const Key &key)

T take(const Key &key)
  • 查找

bool contains(const Key &key) const
    
QHash::iterator find(const Key &key)
QHash::const_iterator find(const Key &key) const
  • 判断

int count(const Key &key) const
int count() const
int size() const
    
bool empty() const

 

2.2.4 QMultiHash

继承自QHash

typename QHash<Key, T>::iterator replace(const Key &key, const T &value)
  • 案例

class Grade //班级
{
public:
    Grade(int number, const QString& GradeName)
        :number(number),name(GradeName)
    {}
    friend QDebug operator<<(QDebug out, const Grade& stu);
    friend bool operator==(const Grade& left, const Grade& right);
    friend uint qHash(const Grade& stu, uint seed = 0);
private:
    int number;     //班级号
    QString name;   
};
QDebug operator<<(QDebug out, const Grade& stu)
{
    out << "[" << stu.number <<"," << stu.name << "]";
    return out;
}
bool operator==(const Grade& left, const Grade& right)
{
    return (left.number == right.number);
}
uint qHash(const Grade& stu, uint seed)
{
    return stu.number;
}

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

    QHash<Grade, QString> hash;
    hash.insert(Grade(1403, "安卓"), "张三");
    hash.insert(Grade(1406, "苹果"), "李四");

    qDebug() << hash;

    return a.exec();
}

 

2.2.5 QSet

  • 添加数据

QSet::iterator insert(const T &value)
  • 获取数据

QList<T> values() const
QList<T> toList() const
  • 删除数据

void clear()

QSet::iterator erase(QSet::const_iterator pos)
QSet::iterator erase(QSet::iterator pos)
    
bool remove(const T &value)
  • 查找

bool contains(const T &value) const
bool contains(const QSet<T> &other) const
    
QSet::const_iterator find(const T &value) const
QSet::iterator find(const T &value)
  • 其他

int count() const
bool empty() const
bool isEmpty() const
int size() const
  • 交集,差集,并集

//并集:ohter集合中不在这个集合中的每一项都被插入到这个集合中。 返回对该集合的引用。      
QSet<T> &unite(const QSet<T> &other)
//差集:从该集合中删除包含在ohter集合中的所有项。 返回对该集合的引用。  
QSet<T> &QSet::subtract(const QSet<T> &other)
//交集:从该集合中删除ohter集合中不包含的所有项。 返回对该集合的引用。      
QSet<T> &intersect(const QSet<T> &other)
//如果该集合与ohter集合至少有一个共同项,则返回true。      
bool intersects(const QSet<T> &other) const

 

 

3. 算法

直接使用STL中的算法

3.1 QtGlobal

Qt类的头文件都会包含该头文件,所以不用再显式定义了

T qAbs(const T &t)	//求绝对值
//返回value限定在min至max范围之内的值
const T &qBound(const T &min, const T &val, const T &max)
//如果p1和p2近似相等,返回true
bool qFuzzyCompare(double p1, double p2)
bool qFuzzyCompare(float p1, float p2)
//如果浮点数约等于0,返回true    
bool qFuzzyIsNull(double d)
bool qFuzzyIsNull(float f)
//返回无穷大的数    
double qInf()
//求最大值和最小值
const T &qMax(const T &a, const T &b)
const T &qMin(const T &a, const T &b)
//四舍五入到最近的整数
qint64 qRound64(double d)
qint64 qRound64(float d)
int qRound(double d)
int qRound(float d)
//获得Qt版本    
const char *qVersion()

 

3.2 QtMath

常用函数

qreal qAcos(qreal v)
qreal qAsin(qreal v)
qreal qAtan2(qreal y, qreal x)
qreal qAtan(qreal v)
int qCeil(qreal v)
qreal qCos(qreal v)
//角度转弧度    
float qDegreesToRadians(float degrees)
double qDegreesToRadians(double degrees)
qreal qExp(qreal v)
qreal qFabs(qreal v)
int qFloor(qreal v)
qreal qLn(qreal v)
quint32 qNextPowerOfTwo(quint32 value)
quint64 qNextPowerOfTwo(quint64 value)
quint32 qNextPowerOfTwo(qint32 value)
quint64 qNextPowerOfTwo(qint64 value)
qreal qPow(qreal x, qreal y)
float qRadiansToDegrees(float radians)
double qRadiansToDegrees(double radians)
qreal qSin(qreal v)
qreal qSqrt(qreal v)
qreal qTan(qreal v)

含义
M_E 自然对数的底 (欧拉数)
M_LOG2E 以2为底e的对数
M_LOG10E 以10为底的e的对数
M_LN2 2的自然对数
M_LN10 10的自然对数
M_PI π
M_PI_2 π/2
M_PI_4 π/4
M_1_PI 1/π
M_2_PI 2/π
M_2_SQRTPI 2除以π的平方根,2 /√π
M_SQRT2 根号2
M_SQRT1_2 1/√π

 

posted @ 2023-08-31 11:51  [BORUTO]  阅读(54)  评论(0编辑  收藏  举报