哈希表实现

哈希表实现:

使用BKDRHash作为基础的哈希函数,同时使用拉链法作为冲突处理方法,实现哈希表的插入和查找操作。

哈希函数BKDRHash实现如下:

1 //映射方法,BKDRHash方法
2 static int32_t BKDRHash(const string& str){
3     int32_t hash=0,seed = 131;
4     for(uint32_t i=0;i<str.length();i++){
5         hash = hash * seed + str[i];
6     }
7     return (hash & 0x7fffffff);
8 }

处理冲突的方法有拉链法,开放定址和再哈希法。各种冲突方法如何实现,可以自行查资料进行学习,这里不做详细介绍。另附一张图,说明拉链法(说明版权:来源小象学院huge的算法讲解PPT)。

程序实现:

  1 /***************************************
  2 FileName :HashTable.cpp
  3 Author : godfrey
  4 CreatedTime : 2016/5/1
  5 ****************************************/
  6 #include <iostream>
  7 #include <cstring>
  8 #include <stdio.h>
  9 #include <stdlib.h>
 10
 11 using namespace std;
 12
 13 class hash_node{
 14 public:
 15     hash_node() {
 16         this->data = "";
 17         this->next = NULL;
 18     }
 19     ~hash_node() {}
 20     void SetData(string data){
 21         this->data = data;
 22     }
 23     string GetData(){
 24         return this->data;
 25     }
 26     void SetNext(hash_node* next){
 27         this->next = next;
 28     }
 29     hash_node* GetNext(){
 30         return this->next;
 31     }
 32 private:
 33     string data;
 34     hash_node* next;
 35 };
 36
 37 class hash_table{
 38 public:
 39     hash_table(int32_t hash_table_len,int32_t node_pool_len){
 40         this->hash_table_len = hash_table_len;
 41         this->node_pool_len = node_pool_len;
 42         this->node_pool_cnt = 0;
 43         try{
 44             this->hash_table_main = new hash_node*[this->hash_table_len];
 45             memset(this->hash_table_main,0,sizeof(hash_node*)*(this->hash_table_len));
 46             this->hash_node_pool = new hash_node[this->node_pool_len];
 47         }catch(const bad_alloc & e){
 48             std::cerr<<"there is no more place"<<endl;
 49         }
 50     }
 51     ~hash_table(){
 52         delete[] this->hash_table_main;
 53         delete[] this->hash_node_pool;
 54     }
 55     //哈希表的插入操作,使用拉链法
 56     bool insert(string str,bool& Is_uniqe){
 57         if(true == this->search(str)){
 58             Is_uniqe = false;
 59             return true;
 60         }
 61         //拉链法插入
 62         hash_node* p;
 63         hash_node* q = this->GetNewNode();
 64         if(q == NULL) return false;
 65         int32_t index = this->GetHashIndex(str);
 66         p = this->hash_table_main[index];
 67         q->SetData(str);
 68         q->SetNext(p);
 69         this->hash_table_main[index] = q;
 70         Is_uniqe = true;
 71         return true;
 72     }
 73     //哈希表的查找操作
 74     bool search(string str){
 75         int32_t index = this->GetHashIndex(str);
 76         hash_node* p = this->hash_table_main[index];
 77         while(p){
 78             if(p->GetData()==str) return true;
 79             p = p->GetNext();
 80         }
 81         return false;
 82     }
 83 private:
 84     hash_node** hash_table_main;//哈希表的大小
 85     hash_node* hash_node_pool;//哈希表的内存池
 86
 87     int32_t hash_table_len,node_pool_len,node_pool_cnt;
 88     //映射方法,BKDRHash方法
 89     static int32_t BKDRHash(const string& str){
 90         int32_t hash=0,seed = 131;
 91         for(uint32_t i=0;i<str.length();i++){
 92             hash = hash * seed + str[i];
 93         }
 94         return (hash & 0x7fffffff);
 95     }
 96     //获取哈希表中字符串相应的索引
 97     int32_t GetHashIndex(string& str){
 98         if(hash_table_len == 0) return 0;
 99         return (hash_table::BKDRHash(str)%this->hash_table_len);
100     }
101     //在内存池中获取新的节点内存
102     hash_node* GetNewNode(){
103         if(this->node_pool_cnt>=this->node_pool_len) return NULL;
104         return &this->hash_node_pool[node_pool_cnt++];
105     }
106 };
107
108 int main()
109 {
110     hash_table ht(100,1000);
111     bool is_uniqe,flag;
112     ht.insert("godfrey",is_uniqe);
113     cout<<"ht.insert godfrey : "<<is_uniqe<<endl;
114     ht.insert("good",is_uniqe);
115     cout<<"ht.insert good : "<<is_uniqe<<endl;
116     ht.insert("godfrey",is_uniqe);
117     cout<<"ht.insert godfrey twice : "<<is_uniqe<<endl;
118     flag = ht.search("godfrey");
119     cout<<"ht.search godfrey : "<<flag<<endl;
120     return 0;
121 }

运行结果:

转载请注明出处:

C++博客园:godfrey_88

http://www.cnblogs.com/gaobaoru-articles/

时间: 2024-10-21 00:18:21

哈希表实现的相关文章

哈希表

哈希表支持的一种最有效的检索方法:散列. 由于计算哈希值和在数组中进行索引都只消耗固定时间,因此哈希表的最大亮点在于他是一种运行时间在常量级的检索方法. 哈希表主要有两种: 1.链式哈希表:将数据存储在桶中的哈希表,每个桶里面都是一个链表,且链表的容量随着冲突的增大而增大.(换句话说就是如果有冲突,会在桶中的链表加上一个存储的值) 2.开地址哈希表:将数据存在表本身,而不是在桶中,他通过各种探查方法来避免冲突. 解决冲突: 不管在以上那种哈希表中,我们的目标是尽可能均匀的分配表中的元素.所以我们

8. 蛤蟆的数据结构进阶八哈希表相关概念

8. 蛤蟆的数据结构进阶八哈希表相关概念 本篇名言:"作家当然必须挣钱才能生活,写作,但是他决不应该为了挣钱而生活,写作.--马克思" 前些笔记我们学习了二叉树相关.现在我们来看下哈希表.这篇先来看下哈希表的相关概念 欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/47347273 1.  哈希表的概念 哈希表(HashTable)也叫散列表,是根据关键码值(Key Value)而直接进行访问的数据结构.它通过把关键

哈希表——线性探测法、链地址法、查找成功、查找不成功的平均长度

一.哈希表 1.概念 哈希表(Hash Table)也叫散列表,是根据关键码值(Key Value)而直接进行访问的数据结构.它通过把关键码值映射到哈希表中的一个位置来访问记录,以加快查找的速度.这个映射函数就做散列函数,存放记录的数组叫做散列表. 2.散列存储的基本思路 以数据中每个元素的关键字K为自变量,通过散列函数H(k)计算出函数值,以该函数值作为一块连续存储空间的的单元地址,将该元素存储到函数值对应的单元中. 3.哈希表查找的时间复杂度 哈希表存储的是键值对,其查找的时间复杂度与元素数

【搜索引擎(二)】索引、倒排索引、哈希表、跳表

索引 其实在计算机中我们早已接触过跟索引有关的东西,比如数据库里的索引(index),还有硬盘文件系统中其实也有类似的东西,简而言之,索引是一种为了方便找到自己需要的东西而设计出来的条目,你可以通过找索引找到自己想要内容的位置.索引过程是: 关键字->索引->文档.在图书馆内的书分门别类,就是一种按类别来分的索引.当然索引还有很多其他的实现. 仅仅有索引的概念是不够的.虽然分门别类是一种方法,但是我们在拥有一堆文档的时候必须要有从文档到索引的规范过程,并且索引的结构要满足能够让人(或者计算机)

哈希表的简单操作

哈希表中,关键值通过哈希函数映射到数组上,查找时通过关键值直接访问数组.哈希表的关键问题在于哈希函数的构造和解决冲突的方法. 下面采用最简单的线性探测展示一下哈希表的基本操作: 1 //Hashtable 2 class HashTable { 3 private: 4 string *elem; 5 int size; 6 public: 7 HashTable() { 8 size = 2000; 9 elem = new string[size]; 10 for (int i = 0; i

Stack集合 Queue队列集合 Hashtable哈希表

Stack集合 干草堆集合 栈集合 栈;stack,先进后出,一个一个赋值,一个一个取值,安装顺序来. 属性和方法 实例化 初始化 Stack st = new Stack(); 添加元素 1 个数 2 Console.WriteLine(st.Count); 3 只要使用一次pop方法,就会从最后一个元素开始排除 弹出 4 Console.WriteLine(st.Pop()); 5 Console.WriteLine(st.Count); 6 只想查看不弹出 7 Console.WriteL

深入理解哈希表

有两个字典,分别存有 100 条数据和 10000 条数据,如果用一个不存在的 key 去查找数据,在哪个字典中速度更快? 有些计算机常识的读者都会立刻回答: “一样快,底层都用了哈希表,查找的时间复杂度为 O(1)”.然而实际情况真的是这样么? 答案是否定的,存在少部分情况两者速度不一致,本文首先对哈希表做一个简短的总结,然后思考 Java 和 Redis 中对哈希表的实现,最后再得出结论,如果对某个话题已经很熟悉,可以直接跳到文章末尾的对比和总结部分. 哈希表概述 Objective-C 中

哈希表(开链法)

纯代码 #pragma once #include <iostream> #include <vector> using namespace std; struct __HashFuncString { size_t operator()(const string &key) { size_t hash = 0; for (size_t i = 0; i < key.size(); ++i) { hash += key[i]; } return hash; } };

哈希表/散列表

哈希表/散列表,是根据关键字(key)直接访问在内存存储位置的数据结构. 构造哈希表的常用方法: 直接地址法---取关键字的某个线性函数为散列地址,Hash(Key) = Key或Hash(key) = A*Key + B, A,B为常数. 除留余数法---取关键值被某个不大于散列表长m的数p除后的所得的余数为散列地址. Hash(key) = key % p. 若采用直接地址法(Hash(Key) = Key)存在一定的缺陷. 当Key值特别大时,而Key之前的数很少,就会造成空间浪费.大多时

哈希表线性探测

HashTable-散列表/哈希表,是根据关键字(key)而直接访问在内存存储位置的数据结构. 它通过一个关键值的函数将所需的数据映射到表中的位置来访问数据,这个映射函数叫做散列函数,存放记录的数组叫做散列表. 哈希冲突/哈希碰撞 不同的Key值经过哈希函数Hash(Key)处理以后可能产生相同的值哈希地址,我们称这种情况为哈希冲突.任意的散列函数都不能避免产生冲突. 我给大家介绍的是哈希表的线性探测,线性探测的基本思路: 1.用一个数据除以散列表的长度,余数是多少,就把这个数放在散列表下标相同