关于Hash Table, 总结如下:

散列表能够实现通过key 对元素的快速访问。 而且易于扩展。 对元素能够实现快速访问(搜索等字典操作), 这是Hash Table 较之于链表的优势所在, 二者均易于扩展。 而易于扩展这个dynamic的结构(使用链接法的时候)又是较之于array的优势所在。  因为数组时不易于扩展的。

使用散列表, 我们需要使用Hash function。 散列函数是对关键字和散列表元提供映射的函数。 常见的Hash function 有如下几种:

(1)直接寻址法。  取关键字或关键字的某个线性函数值为散列地址。即H(key)=key或H(key) = a•key + b,其中a和b为常数(这种散列函数叫做自身函数)

(2)除法散列法, 关键字k 除以m 取余数, 将关键字k 映射到m个slots 中的一个上, 即 h(k) = k mod m, 一般取m 为素数。

(3)乘法散列法: 包含两步:

step 1:用关键字k 乘上常数A(0<A <1), 并提取kA d的小数部分。

step 2: 用m 乘以这个小数部分的值, 再往下取整,

总之, 散列函数为: h(k) = floor(m(kA mod 1))。 乘法散列的好处就是m 可以是2的某个次幂。 而不只是素数了。

(4) 折叠法: 将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为哈希地址。

等等还有好多散列函数。

散列函数的性能直接影响着散列表数据结构的性能。 当散列函数把太少或太多关键字映射到单个散列表元上时,散列表的使用效率会大大降低。

性能最好的散列函数被称为完全散列函数。即保证所有可能的关键字都会分别映射到唯一的散列表元编号上。

通常很难找到一个完全散列函数。 不完全的散列函数就会导致冲突的发生。 冲突是散列表的一个缺点之一。

一般而言, 冲突是无法避免的。 因为关键字的域是无穷的, 而映射到的表中, 表的大小是一定的, 不可能是无穷大的。

既然无法避免冲突, 那么我们就要解决冲突, 解决办法有如下几种:

方法一: 开放寻址法(open addressing):

所有的元素都在散列表中。 不会像链接法那样, 这里没有链表, 也没有链表存放在散列表外。 缺点是散列表可能被插满了。 而且此时的Hash Table也不容易扩展, 即不是dynamic的了。 我们希望我们的散列函数实现均匀散列(uniform hashing), 即每个关键字等可能的插入到slot 中。 但是这只是理想, 通常情况下, 会出现cluste的现象。 出现冲突的时候, 有三种方法用于探查开放寻址中的探查序列:(1)Linear probing(线性探查)(2)二次探查 (3)双重探查。

方法二: 链接法(chaining)。 不难看出此时我们的Hash Table 变成了dynamic的了。 使用允许一个散列表元放置多个元素的方法,这时实际上散列表就是一个链表数组

基于链接法的C++代码如下:

hashtable.h

#ifndef HASHTABLE_H
#define HASHTABLE_H#include <iostream>
#include <cstdlib>
#include <string>using namespace std;class Hash
{
private:struct item{string name;string drink;item* next;item(): name("empty"), drink("empty"), next(nullptr) {}item(string n, string d): name(n), drink(d), next(nullptr) {}};static const int tableSize = 10;  // 存储量可改变item* HashTable[tableSize];public:int hashFunction(string key);Hash();~Hash();void AddItem(string name, string drink);int NumberOfItemsInIndex(int index);void PrintTable();void PrintItemsInIndex(int index);void FindDrink(string name);void RemoveItem(string name);};#endif // HASHTABLE_H

hashtable.cpp

#include "hashtable.h"Hash::Hash()
{for (int i = 0; i < tableSize; ++i){HashTable[i] = new item();HashTable[i]->name = "empty";HashTable[i]->drink = "empty";HashTable[i]->next = nullptr;}
}Hash::~Hash()
{}int Hash::hashFunction(string key)
{int sum = 0;int index;for (size_t i = 0; i < key.size(); ++i){sum += static_cast<int>(key[i]);}index = sum % tableSize;cout << "key[0] = " << key[0] << endl;cout << "key[0] = " << static_cast<int>(key[0]) << endl;cout << "key[1] = " << key[1] << endl;cout << "key[2] = " << key[2] << endl;cout << "sum = " << sum << endl;cout << "index = " << index << endl << endl;return index;
}void Hash::AddItem(string name, string drink)
{int index = hashFunction(name);if (HashTable[index]->name == "empty"){HashTable[index]->name = name;HashTable[index]->drink = drink;}else{item* p = HashTable[index];item* n = new item(name, drink);while (p->next != nullptr){p = p->next;}p->next = n;}
}int Hash::NumberOfItemsInIndex(int index)
{int count = 0;if (HashTable[index]->name == "empty"){return count;}else{count++;item* p = HashTable[index];while (p->next != nullptr){count++;p = p->next;}}return count;
}void Hash::PrintTable()
{int number;for (int i = 0; i < tableSize; ++i){cout << "i = " << i << ": " << endl;number = NumberOfItemsInIndex(i);cout << "index = " << i << ": " << endl;cout << HashTable[i]->name << ", " << HashTable[i]->drink << endl;cout << "# of items = " << number << endl << endl;}
}void Hash::PrintItemsInIndex(int index)
{item* p = HashTable[index];if (p->name == "empty"){cout << "index = " << index << "is empty";}else{cout << "index " << index << " contains the following items \n";while (p != nullptr){cout << p->name << ", " << p->drink <<endl;p = p->next;}}
}void Hash::FindDrink(string name)
{int index = hashFunction(name);bool FindName = false;string drink;item* p = HashTable[index];while (p != nullptr){if (p->name == name){FindName = true;drink = p->drink;}p = p->next;}if (FindName){cout << "Favorite drink " << drink << endl;}else{cout << name << "'s info was not fount in the hash table.\n";}
}void Hash::RemoveItem(string name)
{int index = hashFunction(name);item* delPtr;item* p1;item* p2;// case0: bucket is emptyif (HashTable[index]->name == "empty" &&HashTable[index]->drink == "empty"){cout << name << " was not found in the hash table" << endl;}// case1: only one item contained in the bucket, and that item has matching nameelse if (HashTable[index]->name == name &&HashTable[index]->next == nullptr){HashTable[index]->name = "empty";HashTable[index]->drink = "empty";cout << name << " was removed from the hash table" << endl;}// case 2: match is located in the first item in the bucket and there are more items in the bucketelse if (HashTable[index]->name == name){delPtr = HashTable[index];HashTable[index] = HashTable[index]->next;delete delPtr;cout << name << " was removed from the hash table" << endl;}// case 3: the bucket contains items, but first item is not a matchelse{p1 = HashTable[index]->next;p2 = HashTable[index];while (p1 != nullptr && p1->name != name){p2 = p1;p1 = p1->next;}// case 3.1: no matchif (p1 == nullptr){cout << name << " was not found in the hash table. \n";}//case 3.2: match is foundelse{delPtr = p1;p1 = p1->next;p2->next = p1;delete delPtr;cout << name << " was removed from the hash table" << endl;}}
}

main.cpp

#include "hashtable.cpp"int main()
{Hash hash;string name1 = " ";string name2 = " ";hash.PrintTable();hash.AddItem("Paul", "Locha");hash.AddItem("Kim", "Iced Mocha");hash.AddItem("Anni", "Strawberry Smoothy");hash.AddItem("Sara", "Passion Tea");hash.AddItem("Mike", "Tea");hash.AddItem("steve", "Apple cider");hash.AddItem("Sill", "Root beer");hash.AddItem("Bill", "Lochs");hash.AddItem("Susan", "Cola");hash.AddItem("Joe", "Green Tea");hash.PrintTable();hash.PrintItemsInIndex(0);while (name1 != "exit"){cout << "search for: ";cin >> name1;if (name1 != "exit"){hash.FindDrink(name1);}}cout << endl;while (name2 != "exit"){cout << "Remove: ";cin >> name2;if (name2 != "exit"){hash.RemoveItem(name2);}}hash.PrintTable();hash.PrintItemsInIndex(0);return 0;
}

部分运行结果如下:

哈希表(C++实现)相关推荐

  1. 【C#】集合_哈希表_字典_泛型_文件

    数组能做到:存放同种类型数据,且数据个数确定 object类型的数组能满足:放各种类型的数据,确定放多少个,但是随意插入元素,数组做不到 集合能做到:存放各种数据类型,且不确定存放多少个,能做到随意插 ...

  2. PHP哈希表碰撞攻击原理

    哈希表碰撞攻击(Hashtable collisions as DOS attack)的话题不断被提起,各种语言纷纷中招.本文结合PHP内核源码,聊一聊这种攻击的原理及实现. 哈希表碰撞攻击的基本原理 ...

  3. 在C#中应用哈希表(Hashtable)

    一,哈希表(Hashtable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似key/value的键值对,其 ...

  4. 自己写的哈希表以及解决哈希冲突

    哈希表就是键值key-value对,使用hash函数让key产生哈希值,当不同的key产生相同的哈希值时就是哈希冲突了,产生哈希冲突可以使用拉链法. hash.c #include <stdio ...

  5. PHP内核中的哈希表结构

    https://github.com/HonestQiao/tipi/commit/17ca680289e490763a6a402f79afa2a13802bb36 下载:https://github ...

  6. 用开放地址法中的线性探查法解决冲突实现哈希表的运算

    为了更深的理解哈希算法,自己写了用开放地址法中的线性探查法解决冲突实现哈希表的运算. /*** Created by lirui on 14-8-13.* 用开放地址法中的线性探查法解决冲突实现哈希表 ...

  7. 散列表查找(哈希表)

    散列函数构造经常要考虑: 1.散列表的长度 2.关键字的长度 3.关键字的分布情况 4.计算散列函数所需的时间 5.记录的查找频率 一个"好"的散列函数应遵循一下两条原则 (1)函 ...

  8. 不同表结构数据迁移_数据结构:哈希 哈希函数 哈希表

    写在前面 希望你们看了能够有所收获,同时觉得不错的朋友可以点赞和关注下我,以后还会有更多精选文章分享给大家!大家可以关注一下java提升专栏 java提升​zhuanlan.zhihu.com 什么是 ...

  9. 【数据结构】 哈希表 详解

    目录 1. 概念 引入 2. 冲突 2.1 概念 2.2 避免 2.3 冲突-避免-哈希函数设计 2.4 冲突-避免-负载因子调节(重点) 2.5 冲突-解决 2.5.1 闭散列 2.6 冲突-解决- ...

  10. 数组-丢失的数字(哈希表法)

    题意: 给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数. 示例 1: 输入:nums = [3,0,1] 输出:2 解释:n = 3 ...

最新文章

  1. linux基础(day22)
  2. java linux urlencode_java字符编码转换研究(转)
  3. Intellij页面汉字乱码问题
  4. Android StateFlow详解
  5. 我也来说说Dynamic
  6. 在ubuntu用arm ds-5社区版配合linaro交叉编译工具开发android linux应用
  7. vs2008C1902程序数据库管理不匹配
  8. 字符数组,字符串、数字转化
  9. Spark streaming消费Kafka的正确姿势
  10. arm的bin二进制代码分析
  11. java多线程 同一资源_同一资源多线程并发访问时的完整性
  12. json html api文档,jsonEditor api介绍
  13. ios是什么?ios有什么特点?
  14. 【软件】DVDStyler报错找不到VOB文件
  15. 小案例--封装jsonp
  16. 华为系统取名鸿蒙,华为自主操作系统为何取名鸿蒙?看完西游记就知道霸气在哪里!...
  17. 关于有氧运动的误区 你知道几个
  18. 融资租赁业务系统整体介绍(一)
  19. HTML5音频标签audio无法播放的问题
  20. 【算法】广度优先遍历 (BFS)

热门文章

  1. 视频教程-Unity快速入门系列课程(第1部)-Unity3D
  2. 2021全球网站流量最高的网站,Python 带你看一看
  3. 惠普计算机X9W2AV参数,康佳42MS96PD 全市最低价3D电视
  4. 干货 | 自闭症预测 You can you up
  5. x264代码剖析(十一):核心算法之宏块分析函数x264_macroblock_analyse()
  6. 深度学习笔记-----多输入网络 (Siamese网络,Triplet网络)
  7. Keras 多GPU mult_gup_model 报错 cannot import name ‘multi_gpu_model’ from ‘keras.utils’
  8. 建站建站分享:提取网站整站链接,批量提交,加速网站收录!
  9. 采集爬虫中,解决网站限制IP的问题? - wendi_0506的专栏 - 博客频道 - CSDN.NET
  10. 小天才网络adb_小天才电话手表拨号盘代码大全 又快又好