最近需要学习Hash了,简单了解下Hash的思想就是用空间换时间,先从如何使用开始了解Hash吧
文章目录
- QHash Class
- Public Types
- Public Functions
- Detailed Description
- Member Type Document
- Member Function Documentation
- QHash::QHash()
- QHash::QHash(std::initializer_list< std::pair< Key, T>> list)
- QHash::QHash(const QHas< K, V> &other)
- QHash::QHash(QHas< K, V> &&other)
- QHash::~QHash()
- QHash::iterator QHash::begin()
- QHash::const_iterator QHash::begin() const
- int QHash::capacity() const
- QHash::const_iterator QHash::cbegin() const
- QHash::const_iterator QHash::cend() const
- void QHash::clear()
- QHash::const_iterator QHash::constBegin() const
- QHash::const_iterator QHash::constEnd() const
- QHash::const_iterator QHash::constFind(const Key &key) const
- QHash::const_key_value_iterator QHash::constKeyValueBegin() const
- QHash::const_key_value_iterator QHash::constKeyValueEnd() const
- bool QHash::contains(const Key &key) const
- int QHash::count(const Key &key) const
- int QHash::count() const
- bool QHash::empty() const
- QHash::iterator QHash::end()
- QHash::const_iterator QHash::end() const
- QPair
QHash Class
QHash类是一个模板类,可以提供一个哈希表为基础的字典
Header:#include QHash
qmake:QT += core
继承于:QMultiHash
Public Types
class const_iterator
class iterator
class key_iterator
typedef Constlterator
typedef Iterator
typedef const_key_value_iterator
typedef difference_type
typedef key_type
typedef key_value_iterator
typedef mapped_type
typedef size_type
Public Functions
QHash()
QHash(std::initializer_list<std::pair<Key, T>>list)
QHash(const QHash<K, V> &other)
QHash(QHash<K, V> &&other)
~QHash()
QHash::iterator begin()
QHash::const_iterator begin() const
int capacity() const
QHash::const_iterator cbegin() const
QHash::const_iterator cend() const
void clear()
QHash::const_iterator constBegin() const
QHash::const_iterator constEnd() const
QHash::const_iterator constFind(const Key &key) const
QHash::const_key_value_iterator constKeyValueBegin() const
QHash::const_key_value_iterator constKeyValueEnd() const
bool contains(const Key &key) const
int count(const Key &key) const
int count() const
bool empty() const
QHash::iterator end()
QHash::const_iterator end() const
QPair<QHash::iterator, QHash::iterator> equal_range(const Key &key)
QPair<QHash::const_iterator, QHash::const_iterator> equal_range(const Key &key) const
QHash::iterator erase(QHash::const_iterator pos)
QHash::iterator erase(QHash::iterator pos)
QHash::iterator find(const Key &key)
QHash::const_iterator find(const Key &key) const
QHash::iterator insert(const Key &key, const T &value)
QHash::iterator insertMulti(const Key &key, const T &value)
bool isEmpty() const
const Key key(const T &value) const
const Key key(const T &value, const Key &defaultKey) const
QHash::key_iterator keyBegin() const
QHash::key_iterator keyEnd() const
QHash::key_value_iterator keyValueBegin()
QHash::const_key_value_iterator keyValueBegin() const
QHash::const_key_value_iterator keyValueEnd() const
QList<Key> keys() const
QList<Key> keys(const T &value) const
int remove(const Key &key)
void reserve(int size)
int size() const
void squeeze()
void swap(QHash<K, V> &other)
T take(const Key &key)
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
bool operator != (const QHash<K, V> &other)
QHash<K, V> & operator = (const QHash<K, V> &other)
QHash<K, V> & operator = (QHash<K, V> &&other)
bool operator == (const QHash<K, V> & other) const
T & operator[] (const Key &key)
const T operator[] (const Key &key) const
Detailed Description
QHash类是一个模板类,它提供了一个基于哈希表对的字典
QHash<Key, T> 是Qt的一个常规容器类,它成对储存了数据(键,值),然后提供了一个非常快速的通过Key来寻找值的方法
QHash提供了一个和QMap很相似的操作方法,但是其中不同的地方是:
- QHash可以实现比QMap更快的查询操作
- 当遍历QMap的时候,项目是通过Key的排序来实现的,但是再QHash中,项目的位置是随机的
- QMap中键的类型一定提供了运算符<(),QHash中的键的类型一定提供了运算符==()和一个全局hash函数,名为qHash()
下面一个使用QString作为键,int作为值得例子
QHash<QString, int> hash;
hash["one"] = 1;
hash["three"] = 3;
hash["seven"] = 7;
上面的方法将在QHash中插入三对键:(“one”, 1), (“three”, 3), 还有(“seven”, 7),另一种插入hash中的方式是使用函数insert():
hash.insert("twelve", 12);
使用操作符[]或者函数value()来查找值
int num1 = hash["thirteen"];
int num2 = hash.value("thirteen");
如果没有查找到相关的值,函数将返回默认构造函数的值
使用函数contains()来查看是否hash中有某个键
int timeout = 30;
if (hash.contains("TIMEOUT"))
timeout = hash.value("TIMEOUT");
同样还有一个value的重载函数,我们可以使用它来判断hash中的特定的值
int timeout = hash.value("TIMEOUT", 30);
通常来说,我们建议你使用函数contains和value(),而不是使用操作符,原因是操作符在没有找到key的时候会在hash中插入一个值,举个例子,下面的代码片段将在内存够中创造1000个对象
//WRONG
QHsh<int, QWidget *> hash;
for (int i = 0; i < 1000; ++i) {
if (hash[i] == okButton) {
cout << "Found button at index " << i << endl;
}
}
在内部,QHash使用哈希表来执行查找,哈希表可以自动的增长和缩小,可以提供快速的查找,从而不浪费太多的空间,如果你知道QHash大概需要储存多少的是数据,你可以仍然使用函数reserve()来控大小。但这样的话性能不一定好,如果你想恢复哈希表的大小的话,使用函数capacity()
如果你想遍历hash中的所有的值,你可以使用迭代器,QHash提供了java风格的迭代器和STL风格的迭代器,下面展示了如何使用java风格的迭代器
QHashIterator<QString, int> i(hash);
while (i.hasNext()){
i.next();
cout << i.key() << ": " << i.value() << endl;
}
下面展示了STL风格的迭代器
QHash<QString, int>::const_iterator i = hash.constBegin();
while (i != hash.constEnd()) {
cout << i.key() << ": " << i.value() << endl;
}
QHash的排序是无序的,如果需要有序的,使用QMap
通常来说,QHash仅允许一个值有一个键,如果你想在QHash中插入一个相同Key的值,之前的值将会清除,举个例子
hash.insert("plenty", 100);
hash.insert("plenty", 200);
// hash.value("plenty") = 200
如果你想在一个Key中储存多个值,请使用函数insertMulti()替代insert()(或者使用另外一个便捷子类 QMultiHash),如果你想检索一个Key的所有值,你可以使用 values(const Key &key),该函数将返回一个QList< T >:
QList<int> values = hash.values("plenty");
for (int i = 0; i < values.size(); ++1) {
cout << values.at(i) << endl;
}
共享同一个key的元素在最近的到最近的是可用的,更高效的访问方式是调用函数call(),这样可以获取到…看代码吧
QHash<QString, int>::iterator i = hash.find("plenty");
while (i != hash.end() && i.key() == "plenty") {
cout << i.value() << endl;
++i;
}
如果你想从一个hash中提取出值,你可以使用函数 foreach()
QHash<QString, int> hash;
...
foreach (int value, hash) {
cout << value << endl;
}
从hash中可以通过多种方式来移除数据,一种方式是调用函数remove(),这种方式是通过给定的key来移除项目,另一个方式是使用函数 QMutableHashIterator::remove(),如果你想清除整个hash,使用函数clear()
Qhash的值一定是一种数据类型,比如,你不可以在QHash中储存一个QWidget,但是可以储存一个QWidegt*
The qHash() hashing function
一个QHash的key的类型的key的类型除了是一个数据类型外还需要附加的条件:它一定支持运算符==(),而且该类型的命名空间需要有一个qHash()
qHash()函数基于key计算出一个数值,它将会使用任何可能的算法,一旦key的名称相同,则有qHash(e1)和qHash(e2)相同,qHash()函数尽力去对不同的Key设置不同的值
对于一个key的类型 K,qHash函数一定有如下形式
uint qHash (K key);
uint qHash (const K &key);
uint qHash (K key, uint seed);
uint qHash (const K &key, uint seed);
这两个参数重载生成一个无符号的整型数值,这个值可以用来作为计算的算子,算子是由QHash提供的,目的是为了防止一些列的算法复杂度的攻击,一个参数和两个参数的重载都对一个Key值定义,则后面的将会被QHash所使用
下面的C++类型和Qt类型的类型可以作为QHash的Key:所有的整型,所有的指针类型,QChar,QString,QByteArray,另外QHash头文件定义了qHash()函数可以计算出充足的哈希值,其他的很多类也可以通过声明qHash重载他们的类型
如果你想使用其他类型作为key,请确保你提供了运算符==()和qHash()重载
#ifndef EMPLOYEE_H
#define EMPLOYEE_H
class Employee
{
public:
Employee() {}
Employee(const QString &name, const QDate &dataOfBirth);
...
private:
QString myName;
QDate myDateOfBirth;
};
inline bool operator==(const Employee &e1, const Employee &e2)
{
return e1.name() == e2.name()
&& e1.dateOfBirth() == e2.dateOfBirth();
}
inline uint qHash(const Employee &key, uint seed)
{
return qHash(key.name(), seed) ^ key.dateOfBirth().day();
}
#endif // EMPLOYEE_H
在上面的例子中,我们依靠Qt的全局函数qHash(const QString &, uint),提供一个关于雇佣名的一个哈希值,并且使用XOR运算来计算出唯一的哈希值
算法复杂性冲击
所有的哈希表都容易受到特定类的服务攻击
Member Type Document
typedef QHash::Constlterator
QHash::const_iterator的Qt样式的同义词
typedef QHash::Iterator
QHash::iterator的Qt风格的同义词
typedef QHash::const_key_value_iterator
QMap::const_key_value_iterator 定提供了一个QHash的迭代器,还有QMultiHah
typedef QHash::difference_type
定义ptrdiff_t,提供STL兼容性
typedef QHash::key_type
定义Key,提供STL兼容性
typedef QHash::key_value_iterator
QMap::key_value_iterator为QHash和QMultiHash提供了一个STL风格的迭代器
typedef QHash::mapped_type
为T.Provided提供STL兼容性
typedef QHash::size_type
为int.Provided提供STL兼容性
Member Function Documentation
QHash::QHash()
构造空的QHash
QHash::QHash(std::initializer_list< std::pair< Key, T>> list)
类似于列表初始化
QHash::QHash(const QHas< K, V> &other)
根据其他的构造QHash 构造相同的QHash
QHash::QHash(QHas< K, V> &&other)
Move-constructs 一个QHash实例,使其和other指向的相同的对象
QHash::~QHash()
析构函数
QHash::iterator QHash::begin()
返回STL风格的的指向QHash的第一个项目的迭代器
QHash::const_iterator QHash::begin() const
这是一个重载函数
int QHash::capacity() const
返回Qhash内部的哈希表的桶数,这个函数的通常只有在微调QHash内存的时候才调用一下,平常是不会调用的,如果你想知道hash中有多少个项目,调用函数size()
QHash::const_iterator QHash::cbegin() const
返回一个指向hash第一个对象的STL风格的迭代器
QHash::const_iterator QHash::cend() const
返回一个指向最后一个项目的很后面的一个STL风格的迭代器
void QHash::clear()
清除所有的hash中的项目
QHash::const_iterator QHash::constBegin() const
返回指向hash中的的第一个项目的STL风格的迭代器
QHash::const_iterator QHash::constEnd() const
返回指向hash中的最后一个项目后面的STL风格的迭代器
QHash::const_iterator QHash::constFind(const Key &key) const
染回指定Key的迭代器,如果hash没有该Key,则返回constEnd()
QHash::const_key_value_iterator QHash::constKeyValueBegin() const
指向hash的第一个entry
QHash::const_key_value_iterator QHash::constKeyValueEnd() const
返回指向hash最后一个项目侯敏的STL风格的迭代器
bool QHash::contains(const Key &key) const
如果hash中包含key,则返回true,否则返回false
int QHash::count(const Key &key) const
返回指定key的值的个数
int QHash::count() const
重载函数
bool QHash::empty() const
类似于函数isEmpty(),只不过反过来了
QHash::iterator QHash::end()
返回hash最后一个项目后面的迭代器
QHash::const_iterator QHash::end() const
这是一个重载函数
QPair<QHash::iterator, QHash::iterator> QHash::equal_range(const Key &key)
返回代表值的范围[first, second)的一对迭代器,这里面在key中储存,如果range是空的话,两个迭代器都返回end()
QPair<QHash::const_iterator, QHash::const_iterator> QHash::equal_range(const Key &key) const
重载
QHash::iterator QHash::erase(QHash::const_iterator pos)
移除迭代器pos的key和value,并返回hash的下一个迭代器
和函数remove(),take()不同,该函数不会造成QHash重哈希内部的数据结构,这意味着该函数可以在迭代过程中安全的调用,从而不影响hash中的级别,比如:
QHash<object *, int> objectHash;
...
QHash<Object *, int>::iterator i = objectHash.find(obj);
while (i != objectHash.end() && i.key() == obj) {
if (i.value() == 0) {
i = objectHash.erase(i);
}
else {
++i;
}
}
QHash::iterator QHash::erase(QHash::iterator pos)
重载函数
QHash::iterator QHash::find(const Key &key)
如果key在hash中,则返回迭代器
如果没有在hash中,则返回end()
如果一个Key中有多个值的话,则返回最近插入的那个值,其他的值通过增加迭代器的方式来访问,比如
QHash<QString, int> hash;
...
QHash<QString, int>::const_iterator i = hash.find("HDR");
while (i != hash.end() && i.key() == "HDR") {
cout << i.value() << endl;
++i;
}
///太多了,剩下的需要的时候载看吧