key形式哈希表的线性探测
来源:互联网 发布:linux server 版本官网 编辑:程序博客网 时间:2024/06/05 11:51
一、什么是key形式的哈希表
简单的说就是通过key的来查找key的值
二、线性探测
简单的来说就是遇到哈西冲突就查找下一个位置,看位置上是否有数据,假如有则继续查找,假如没有则将数据放入到当前位置
局限性:引发洪水式的冲突,冲突越来越多,找的越来越慢(因为找到的是一片冲突,找到空才停下来),效率低
二、定义状态数组和仿函数
1、定义状态数组
由于哈希表中每个位置的传值不知道设置为什么具体的值好并且删除后不知道设置成什么具体的值好(设置为-1万一保存的就是-1呢),所以设置一个状态数组用来,表示每一个为值上的值的状态,初始时设置为EMPTY,当前位置上存在数字设置为EXIST,要删除当前位置上的值设置为DELETE(也为懒删除法)enum Status { EXIST, DELETE, EMPTY, };
2.定义仿函数
定义放函数的作用主要还是提高代码的复用性,对于不同类型的数据,其处理的函数是不同的,而其他地方的代码都是相似的,这样就可以定义一个仿函数专门来处理哈希函数不同的问题
//仿函数template<class K>struct DefaulstHashFuncer{size_t operator()(const K& key){return key;}};template<>struct DefaulstHashFuncer <string>//特化string类型的仿函数{static size_t BKDRHash(const char * str)//<span style="color:#ff0000;">字符串的哈希算法</span>{unsigned int seed = 131; // 31 131 1313 13131 131313unsigned int hash = 0;while (*str){hash = hash * seed + (*str++);}return (hash & 0x7FFFFFFF);}size_t operator()(const string& str){return BKDRHash(str.c_str());}};
三、具体实现
1、函数的声明
template<class K, class HashFuncer = DefaulstHashFuncer<K>>class HashTaable{public:HashTaable();HashTaable(size_t size);HashTaable(const HashTaable<K, HashFuncer>& ht);HashTaable<K, HashFuncer>& operator=(HashTaable<K, HashFuncer> ht);~HashTaable();public:bool Insert(const K& key);bool Find(const K& key);bool Remove(const K& key);void PrintTable();void Swap(HashTaable<K>& ht);protected:size_t _HashFunc(const K& key);//哈希函数int _Find(const K& key);void _CheckCapacity();protected:K* _tables;rsize_t _size;Status* _status;//状态数组size_t _capacity;};
2、具体实现
(1)默认构造函数
HashTaable():_tables(NULL), _status(NULL), _size(0), _capacity(0){}
(2)构造函数,传入构造的哈希表的大小
HashTaable(size_t size):_tables(new K[size]), _status(new Status[size]), _size(0), _capacity(size){//for (_status, EMPTY, sizeof(_status)*_size);//枚举类型不能用memsete因为memset是按字节处理for (size_t i = 0; i < _capacity; ++i)//若用memset则里面为随机值{_status[i] = EMPTY;}}
(3)拷贝构造函数
HashTaable(const HashTaable<K, HashFuncer>& ht):_tables(NULL), _status(NULL), _size(0), _capacity(0){HashTaable<K, HashFuncer> tmp(ht._capacity);for (size_t i = 0; i <ht._capacity; ++i){if (ht._status[i] == EXIST)//状态为删除时不用管{tmp.Insert(ht._tables[i]);}}this->Swap(tmp);//冲突改变,相对位置改变}
(4)operator=
HashTaable<K, HashFuncer>& operator=(HashTaable<K, HashFuncer> ht){this->Swap(ht);return *this;}
(5)析构函数
~HashTaable(){if (_tables!=NULL){delete[] _tables;delete[] _status;_tables = NULL;_status = NULL;}}
(6)插入数据(如果数据本身在表中就存在,则返回false)
bool Insert(const K& key){/*if (_size == _capacity){cout << "Full" << endl;return false;}*/_CheckCapacity();size_t index = _HashFunc(key);//线性探测while (_status[index] == EXIST){if (_tables[index] == key){return false;}++index;if (index == _capacity){index = 0;}}_status[index] = EXIST;_tables[index] = key;++_size;return true;}
(7)寻找数据
如果找到则返回true,没有找到返回false
bool Find(const K& key){if (_Find(key) == -1){return false;}return true;}
(8)删除某个记录
使用懒删除法
bool Remove(const K& key){int index = _Find(key);if (index!=-1){_status[index] = DELETE;return true;}return false;}
(9)打印整个哈希表
void PrintTable(){for (size_t i = 0; i < _capacity; ++i){if (_status[i] == EXIST){printf("[%d];E->", i);cout << _tables[i] << endl;}else if (_status[i]==DELETE){printf("[%d];D->", i);cout <<_tables[i];}else{printf("[%d];N", i);cout << endl;}}}
(10)两个哈希表之间发生交换
void Swap(HashTaable<K>& ht){std::swap(_tables, ht. _tables);std::swap(_size, ht._size);std::swap(_status, ht._status);std::swap(_capacity, ht._capacity);}
下面为保护的函数
(11)哈希函数
size_t _HashFunc(const K& key)//哈希函数{HashFuncer hf;return hf(key) % _capacity;}
(13)查找key值所在的位置
int _Find(const K& key){size_t index = _HashFunc(key);//默认哈希表中一定是有空余的位置的while (_status[index] != EMPTY){if (_tables[index] == key&&_status[index] != DELETE){return index;}++index;if (index == _capacity){index = 0;}}return -1;}
(14)增容
void _CheckCapacity(){if (_size * 10 >= _capacity * 7){HashTaable<K> tmp(2 * _capacity);for (size_t i = 0; i < _capacity; ++i){if (_status[i] == EXIST)//状态为删除时不用管{tmp.Insert(_tables[i]);}}this->Swap(tmp);//冲突改变,相对位置改变}}
三、测试用例
void Test(){HashTaable<string> ht1(10);//使用仿函数解决这个问题ht1.Insert("小明");ht1.Insert("杰克");ht1.Insert("明小");ht1.Insert("小军");ht1.PrintTable();cout << endl;HashTaable<string> ht2(ht1);ht2.Insert("123");ht2.PrintTable();cout << endl;ht2 = ht1;ht2.PrintTable();}
0 0
- key形式哈希表的线性探测
- 哈希表线性探测&二次探测
- 哈希表KV形式的二次探测
- 线性探测再散列解决冲突的哈希表
- 线性探测哈希表的java代码
- 【数据结构】哈希表的线性探测算法
- 哈希表的构造之线性探测法
- 哈希表的C++实现(线性探测)
- 哈希表---线性探测法
- 哈希表线性探测再散列
- 哈希表-线性探测
- 哈希表(线性探测再散列)
- 线性探测法构建哈希表
- 实验 哈希表线性探测再散列
- 一个简单的哈希表(线性探测再散列)
- 6-4 线性探测法的查找函数(哈希表)
- 【哈希表】线性探测再散列的相关知识与计算
- 哈希表 除数余留 + 链地址 && 线性探测 && 平方探测
- iOS-CollectionView 基础
- python paramiko模块实现sftp上传下载文件
- Excel ActiveX教程(一)
- 单例设计模式
- CBitmap和HBITMAP的区别及相互转换方法
- key形式哈希表的线性探测
- MySQL之事务、索引、锁
- ios掩藏导航栏下面的线
- [Scikit-Learn] - 数据预处理 - 归一化/标准化/正则化
- Java之抽象类
- 列表控件
- [C++]bitset特殊用法
- 线程
- java之二分法递归显示数列