浅谈一下Hashtable,Hashmap,map

2023-05-16

这里浅谈一下Hashtable,Hashmap,map

1.首先说一下Hashtable 

 

哈希表(Hash Table)也叫散列表,是根据关键码值直接访问 
就是一个把关键码映射到表中的一个位置来访问记录的过程 
这个映射函数叫做哈希函数,用hash()表示,存放记录的数组叫做哈希表(一个数组) 
哈希表是一种高效的数据结构,主要体现在数据的查找上,几乎可以看成常数时间 

 

为了解决hasntable冲突的问题,我这里列举出了两种方法来实现,开放式地址法和链式地址法

 

开放式地址发,以下是我定义的hashtable采用开发式地址法定义的数据结构,Hashtable的每一元素是Elemtype,为了解决冲突采用的hash算法是return ((key%M)+Irc(i))%M,如果hash后映射到有数据存在则采用增量的方式重新哈希

#define M 13

#define Nul -1

#define KeyType int 

 

typedef struct{}Record; //记录级指针

 

typedef struct Elemtype

{

 KeyType key;

 Record *record;

}Elemtype; 

 

 typedef Elemtype HashArray[M]; 

 typedef struct HashTable 

 HashArray Table; 

 int cursize;

 }HashTable;

下面贴出完整的代码

#include

using namespace std;

 

#define M 13

#define Nul -1

#define KeyType int

 

typedef struct{}Record;

 

typedef struct Elemtype

{

KeyType key;

Record *record;

}Elemtype;

 

typedef Elemtype HashArray[M];

 

typedef struct HashTable

{

HashArray Table;

int cursize;

}HashTable;

 

void Init(HashTable *table)

{

table->cursize = 0;

for(int i = 0; i < M; ++i)

{

table->Table[i].key = Nul;

table->Table[i].record = NULL;

}

}

 

int Irc(int i)

{

return i;

}

 

int Hash(KeyType key,int i )

{

return ((key%M)+Irc(i))%M;//增量,解决冲突,当有冲突的时候往后移动

}

 

int Search(HashTable *table,KeyType key)

{

for(int i = 0; i < M; ++i)

{

int pos = Hash(key,i);

if(table->Table[pos].key == Nul)

{

return pos;

}

if(table->Table[pos].key == key)

{

return -1;

}

}

return -1;

}

 

bool Insert(HashTable *table,Elemtype val)

{

bool res = false;

int pos = Search(table,val.key);

 

if(pos != -1)

{

table->Table[pos] = val;

table->cursize += 1;

res = true;

}

return res;

}

以上是采用开发式地址的方法来解决hash冲突。

下面说说第二种方法,采用链式地址的方法来解决hash冲突

EG:如果key1和Key2映射到同一个结点上,则采用链表的形式连起来,如下图所示Hash算法

 

一下是我定义的数据结构

#define M 13

#define NUL -1

#define Keytype int

 

typedef struct{}Record;

 

typedef struct ElemType

{

Keytype key;

Record *record;

}ElemType;

 

typedef struct HashNode

{

ElemType elem;

HashNode *next;

}HashNode;

 

typedef HashNode* HashArray[M];

 

typedef struct HashTable

{

HashArray Table;

int cursize;

}HashTable;

 

也就是说在Hashtable中每一个元素的类型其实是一个结点类型,带头节点的链表,采用此方法来解决链式地址冲突,下面贴出完整的代码

#include

using namespace std;

 

#define M 13

#define NUL -1

#define Keytype int

 

typedef struct{}Record;

 

typedef struct ElemType

{

Keytype key;

Record *record;

}ElemType;

 

typedef struct HashNode

{

ElemType elem;

HashNode *next;

}HashNode;

 

typedef HashNode* HashArray[M];

 

typedef struct HashTable

{

HashArray Table;

int cursize;

}HashTable;

 

HashNode* _BuyNode()

{

HashNode *p = new HashNode;

memset(p,0,sizeof(p));

return p;

}

 

void Init(HashTable *table)

{

table->cursize = 0;

for(int i = 0; i < M; ++i)

{

table->Table[i] = _BuyNode();

table->Table[i]->elem.key = -1;

table->Table[i]->next = NULL;

}

}

 

int Hash(Keytype key)

{

return key%M;

}

 

int Search(HashTable *table,Keytype key)

{

int pos = Hash(key);

HashNode *p = table->Table[pos];

while(p != NULL && p->elem.key != key)

{

p = p->next;

}

if(p == NULL)

{

return pos;

}

else

{

return -1;

}

}

 

bool Insert(HashTable *table,ElemType elem)

{

bool res = false;

int pos = Search(table,elem.key);

if(pos != -1)

{

HashNode *p = _BuyNode();

p->elem = elem;

p->next = table->Table[pos]->next;

table->Table[pos]->next = p;

res = true;

}

return res;

}

以上是采用链式地址发来解决冲突。

 

2.下面谈一下Hashmap,看图Hash算法

 

hashmap是建立在hashtable的基础之上的。两者之间没有太大的区别

采用vector作为数据,而数据里面的元素其实是一个list(链表),把key和value存储成一个pair对象实现了封装。hashtable和hashmap之间的区别如下

重要的不同是Hashtable的方法是同步的,而HashMap的方法不是。这就意味着,虽然你可以不用采取任何特殊的行为就可以在一个多线程的应用程序中用一个Hashtable,但你必须同样地为一个HashMap提供外同步。


只有HashMap可以让你将空值作为一个表的条目的key或value,而hashtable不允许  

Hash算法

这里总结出了hashmap和hashtable的区别

3.下面说一下map

map的底层采用红黑树来实现,map的特点如下

1.祖先结点必须是黑色的

2.叶子结点是黑色的(NULL)结点

3.任意两个相同颜色的结点不能相邻

4.从根结点到叶子节点的所有路径所经过的节点都是相同的

这也是红黑树和VAL树的区别,红黑树和VAL树的时间复杂度都是O(logn),但是红黑并不追求完全平衡,而VAL树则要求左右子树的高度之差不超过1,追求完全平衡。

 

hashmap和map是有区别的,hashmap是基于hashtable来实现的,而map是由红黑树来实现的。

 

以上是我总结出来的几点,如果说的不对的地方,请大家指正,q^q,下一篇接着会讨论hash的扩容问题,和一致哈希算法的实现

转载于:https://my.oschina.net/sosomywork/blog/692670

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

浅谈一下Hashtable,Hashmap,map 的相关文章

  • C 中的布谷鸟哈希

    有没有人有实施布谷鸟哈希 http en wikipedia org wiki Cuckoo hashing在C语言中 如果有一个开源的非 GPL 版本那就完美了 既然 Adam 在评论中提到了它 有人知道为什么它没有被太多使用吗 这只是一
  • 将键->值的哈希映射“转置”为值->键?

    假设我有一个键 gt 值对的映射 我想反转它 以便我有一个新的映射 它实际上是值 gt 键 即旧值成为新键 旧键成为新值 最好的方法是什么 我正在使用Java 哦 价值观是独一无二的 我个人会用番石榴BiMap https google g
  • 当 HashMap 或 HashSet 达到最大容量时会发生什么?

    就在几分钟前 我回答了一个关于 Java中HashMap的最大可能大小 正如我一直读到的那样 HashMap 是一种可增长的数据结构 它的大小仅受 JVM 内存大小的限制 因此我认为它的大小没有硬性限制并做出了相应的回答 这同样适用于 Ha
  • HashMap 反向排序? [复制]

    这个问题在这里已经有答案了 所以我遇到了这个方法 它能够按值对 HashMap 进行排序 public static
  • 为什么这个 HashMap.get 返回 null?

    我正在尝试创建一个Hashmap为我执行查找 但是 当我运行此测试代码时 输 出为空 我认为这与密钥存储方式的性质有关 但我并不肯定 也许这是一个类似的怪癖 就像var1 var2不等于 除非它们指向内存中的同一个对象 而您必须使用var1
  • 检查和删除 Java HashMap 中的元素

    我正在尝试使用 Java 中的 HashMap 检查并删除元素 它的键是我创建的称为 ClusterKey 的类型 它的值是我创建的称为 ClusterValue 的类型 这是导致问题的代码 ClusterKey ck new Cluste
  • 使用双重哈希时,最佳的第二哈希函数是什么?

    我在一些人们使用的论坛上看到 7 key mod 7 or 6 key mod 6 这用于为任何大的键值计算双哈希的第二个哈希函数 使用 6 甚至不是素数 或 7 有什么重要性吗 或者它只是随机生成一些值 与线性探测和二次探测不同 参考 h
  • 统一哈希函数

    哈希表基础知识 主要测试即将进行 我们将不胜感激所有帮助 我基本上对密钥的统一散列有点困惑 X X X lt Chains X represents an item in there X X X lt Multiple X represen
  • 用数字替换符号

    我想读取一个文件并检测符号后面的字符是数字还是单词 如果是数字 我想删除它前面的符号 将数字翻译成二进制并替换在文件中 如果是一个单词 我想首先将字符设置为数字16 但随后 如果使用另一个单词 我想在原始数字上添加1 这就是我想要的 如果文
  • 如何断言两个具有 Javabean 值的 HashMap 相等?

    我有两个HashMap
  • Clojure 哈希映射到 xml

    我正在尝试将以下映射转换为 xml 任何具有向量值的键都需要为向量中的每个元素重复 xml 中的键 use clojure xml defn map to xml2 k v cond nil k for e a v tag e conten
  • 如何在 Java 中创建哈希表?

    在 Java 中创建哈希表 或关联数组 最直接的方法是什么 我的 google fu 已经出现了几个例子 但是有一个标准的方法来做到这一点吗 有没有一种方法可以用键 gt 值对列表填充表 而无需为每对对象单独调用 add 方法 Map ma
  • 2d(3d) 坐标的哈希图(即双精度向量)?

    我想知道是否有一个通用的全能解决方案hash map对于坐标 2d 或 3d 即双精度向量 一个例子here https stackoverflow com questions 7222143 unordered map hash func
  • 为什么我们需要 IEqualityComparer,IEqualityComparer 接口?

    Equal 和 GetHashcode 方法存在于对象类中 并且我们的类型继承了对象基类 直接实现对象的两个方法和使用IComparer接口有什么区别 如果我们覆盖对象的 Equal 和 GetHashCode 并推送到哈希表 它将使用覆盖
  • Java HashMap.clear()和remove()内存有效吗?

    考虑以下HashMap clear code Removes all of the mappings from this map The map will be empty after this call returns public vo
  • 如何对 HashMap 键进行排序[重复]

    这个问题在这里已经有答案了 我有一个问题 HashMap
  • unordered_map线程安全

    我正在使用 boost thread 库将单线程程序更改为多线程程序 该程序使用 unordered map 作为 hasp map 进行查找 我的问题是 某一时刻 许多线程将进行写入 而另一时刻 许多线程将进行读取 但不会同时进行读取和写
  • Bash 中的多维关联数组

    我正在尝试创建一个多维关联数组 但需要一些帮助 我已审查过这个SO答案中建议的页面 https stackoverflow com questions 3020713 how to print bash varibles contents
  • 如何按整数值对哈希图进行排序[重复]

    这个问题在这里已经有答案了 HashMap
  • 两个或多个(哈希)映射的并集

    我有两个包含相同类型对象的地图 Map

随机推荐