C++之简单哈希表查找法的实现和循环查找法的比较

来源:互联网 发布:mac终端颜色配置 编辑:程序博客网 时间:2024/06/11 05:07

散列表 (Hash table,也叫哈希表),是根据关键字(Key value)而直接访问在内存存储位置的数据结构。 也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。 这个映射函数称做散列函数,存放记录的数组称做散列表

哈希表、二叉树、链表是最常见的数据结构,涵盖了程序员面试和笔试中几乎所有的数据结构相关问题。 本文中用C++来实现一个简单的哈希表,帮助理解哈希表是怎样运作的。为了简化代码并突出逻辑,采用简单的除余数作为 散列函数 ,用线性探测来 处理碰撞 。

#include <iostream>#include <string>#include <Windows.h>using namespace std;class HashItem{int key, val;public:HashItem(int k, int v) : key(k), val(v){ };const int& getKey(){return key;}const int& getVal(){return val;}};#define LEN 25000*2//#define LEN 8192class HashTable{public:static const int SIZE = LEN+2;//需要SIZE足够大,否则死循环private:HashItem ** table;  // 注意这是二级指针,指向对个HashItem*public:HashTable(){table = new HashItem*[SIZE](); // 这里的括号是为了初始化为0}void set(int key, int val){int idx = key%SIZE;while (table[idx] && table[idx]->getKey() != key)idx = (idx + 1) % SIZE;   // 当SIZE不够大时,这里会陷入死循环。可以检测一下。if (table[idx]) delete table[idx];table[idx] = new HashItem(key, val);}//采用简单的除余数作为散列函数,用线性探测来 处理碰撞。const int get(int key){int idx = key%SIZE;while (table[idx] && table[idx]->getKey() != key)idx = (idx + 1) % SIZE;           // SIZE不够大时,这里也面临死循环的问题return table[idx] ? table[idx]->getVal() : -1;      // 注意这里需要判断key不存在的情况}~HashTable(){for (int i = 0; i<SIZE; i++)if (table[i]) delete table[i];delete[] table; // 别忘了table本身也是要销毁的}};void test_hash(){cout << "test_hash start" << endl;HashTable hash;//set datafor (int i = 0; i < LEN; i++){int fd = i + LEN;//保存fd到全局数组中,作为需要查询的数据hash.set(fd, i);//fd作为key,索引值i作为值。}DWORD   dwBeginTime = GetTickCount();//返回开机以来,经历的毫秒数for (int i = 0; i < LEN; i++){//分别去查询数组中i=key对应的值。int fd = i+LEN+5;int val = hash.get(fd);//使用fd去查询,不存在返回-1,存在则返回他的索引值//cout << "key=" << fd << ",val=" << val<<" ";}cout << endl;WORD   dwEndTime = GetTickCount();WORD cha = (dwEndTime - dwBeginTime);cout << "test_hash end and take time=" << cha << endl << endl;}int search_by_loop(int data[], int key){int j = 0;for (j = 0; j < LEN; j++){if (data[j] == key){break;}}if (j >= LEN)j = -1;return j;}void test_loop(){cout << "test_loop start" << endl;int data[LEN] = {0};//set datafor (int i = 0; i < LEN; i++){int fd = i + LEN;data[i] = fd;//把我的数据fd保存在数组中。}DWORD   dwBeginTime = GetTickCount();//返回开机以来,经历的毫秒数for (int i = 0; i < LEN; i++){//分别查询我的数据int fd = i+LEN+5;int val=search_by_loop(data, fd);//cout << "key=" << fd << ",val=" << val << " ";}cout << endl;WORD   dwEndTime = GetTickCount();WORD cha = (dwEndTime - dwBeginTime);cout << "test_loop end and take time=" << cha << endl << endl;;}//http://www.tuicool.com/articles/uiQRre//C++之简单哈希表查找法的实现和循环查找法的比较(用空间换取时间,提高程序查询的速率,不用循环去查找了)//实际需求都是根据数据去查找的,而不是根据索引值void main(){test_hash();test_loop();cout << "ok" << endl;cout << "结果是哈希表查找法比循环查找法快很多,特别是数据量大的时候!代价是哈希表空间足够大" << endl;int  n;cin >> n;}

#include <iostream>#include <string>#include <Windows.h>using namespace std;class HashItem{int key, val;public:HashItem(int k, int v) : key(k), val(v){ };const int& getKey(){return key;}const int& getVal(){return val;}};#define LEN 25000*2//#define LEN 8192class HashTable{public:static const int SIZE = LEN+2;//需要SIZE足够大,否则死循环private:HashItem ** table;  // 注意这是二级指针,指向对个HashItem*public:HashTable(){table = new HashItem*[SIZE](); // 这里的括号是为了初始化为0}void set(int key, int val){int idx = key%SIZE;while (table[idx] && table[idx]->getKey() != key)idx = (idx + 1) % SIZE;   // 当SIZE不够大时,这里会陷入死循环。可以检测一下。if (table[idx]) delete table[idx];table[idx] = new HashItem(key, val);}//采用简单的除余数作为散列函数,用线性探测来 处理碰撞。const int get(int key){int idx = key%SIZE;while (table[idx] && table[idx]->getKey() != key)idx = (idx + 1) % SIZE;           // SIZE不够大时,这里也面临死循环的问题return table[idx] ? table[idx]->getVal() : -1;      // 注意这里需要判断key不存在的情况}~HashTable(){for (int i = 0; i<SIZE; i++)if (table[i]) delete table[i];delete[] table; // 别忘了table本身也是要销毁的}};int hash_openSize = -1;int loop_openSize = -1;void test_hash(){cout << "test_hash start" << endl;HashTable hash;//set datafor (int i = 0; i < LEN; i++){int fd = i + LEN;//保存fd到全局数组中,作为需要查询的数据hash_openSize++;hash.set(fd, hash_openSize);//fd作为key,索引值i作为值。}DWORD   dwBeginTime = GetTickCount();//返回开机以来,经历的毫秒数for (int i = 0; i < LEN; i++){//分别去查询数组中i=key对应的值。int fd = i+LEN+5;int val = hash.get(fd);//使用fd去查询,不存在返回-1,存在则返回他的索引值//cout << "key=" << fd << ",val=" << val<<" ";}cout << endl;int newfd = 1024;int index = hash.get(newfd);//cout << "index=" << index << endl;if (index == -1)//不在哈希表中则插入新的数据{hash_openSize++;hash.set(newfd, hash_openSize);cout << "hash end set  newfd=" << newfd << endl;}WORD   dwEndTime = GetTickCount();WORD cha = (dwEndTime - dwBeginTime);cout << "test_hash end and take time=" << cha << endl << endl;}int search_by_loop(int data[], int key){int j = 0;for (j = 0; j < loop_openSize; j++){if (data[j] == key){break;}}if (j >= LEN)j = -1;return j;}void test_loop(){cout << "test_loop start" << endl;int data[LEN] = {0};//set datafor (int i = 0; i < LEN; i++){int fd = i + LEN;loop_openSize++;data[loop_openSize] = fd;//把我的数据fd保存在数组中。}DWORD   dwBeginTime = GetTickCount();//返回开机以来,经历的毫秒数for (int i = 0; i < LEN; i++){//分别查询我的数据int fd = i+LEN+5;int val=search_by_loop(data, fd);//cout << "key=" << fd << ",val=" << val << " ";}cout << endl;WORD   dwEndTime = GetTickCount();WORD cha = (dwEndTime - dwBeginTime);cout << "test_loop end and take time=" << cha << endl << endl;;}//http://www.tuicool.com/articles/uiQRre//C++之简单哈希表查找法的实现和循环查找法的比较(用空间换取时间,提高程序查询的速率,不用循环去查找了)//实际需求都是根据数据去查找的,而不是根据索引值void main(){test_hash();test_loop();cout << "ok" << endl;cout << "结果是哈希表查找法比循环查找法快很多,特别是数据量大的时候!代价是哈希表空间足够大" << endl;int  n;cin >> n;}


阅读全文
0 0
原创粉丝点击