热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

哈希表原理及hashmap简单实现

哈希表也叫做散列表。在各种语言中都有hashmap的实现。其最突出的优点是查找和插入以及删除具有常数的时间复杂度我们可以把哈希表理解为数组+链表数组具有常数复杂度

哈希表也叫做散列表。在各种语言中都有hashmap的实现。其最突出的优点是查找和插入以及删除具有常数的时间复杂度

 

我们可以把哈希表理解为数组+链表

数组具有常数复杂度的查找,为什么呢,因为数组是在内存中连续存放,当我们索引某个位置的元素时候根据索引值自动计算距离数组首元素起始位置的内存间隔。然而对于中间插入和中间删除元素,数组会将待插入位置后面的原素先整体向后移动一个位置再将元素插入到待插入的位置。所以时间复杂度为O(n)对于大规模的数组来说,开销是很大的。

 

然而链表正相反。由于链表是存储在内存中不连续的位置,并且链表之间是通过链表指针链接到一起。前一个元素保存后一个元素的指针,我们也称之为前一个元素指向后一个元素。当我们在链表中寻找某个元素的时候必须按照链表指针遍历整个链表,时间复杂度为O(n)但是针对插入很删除来说,我们只需要更改待需要操作的链表元素的指针即可,时间复杂度为O(1). 

 

那么我们可以不可以把两者结合起来组合成一种新的数据结构呢,这种数据结构即能实现常数复杂度的索引也能实现常数复杂度的插入和删除。当然哈希表应运而生。

 

哈希表的原理可以简述为(简述插入和索引操作):

插入:当我们插入hashmap['key']=value时,先将key映射为hashcode,然而用hashcode对哈希表长度取模获得索引位置。然后将值插入到索引位置。(这里可能会存在冲突,即相同的Key的hashcode相同)

 

索引:当我们索引某个值的时候,先将key映射为hashcode,然后将key对哈希表长度取模,然后取出该索引位置上的值。

 

下面我简单实现了一个哈希表,这仅仅是为了说明哈希的原理。

简单hashmap类定义:

 1 #include
 2 using namespace std;
 3 class MySimpleHashmap
 4 {
 5 public:
 6     int *Array;
 7     enum{MaxHashSize=7};
 8 
 9     int hashcode(int &key);
10 
11 public:
12     MySimpleHashmap();
13     ~MySimpleHashmap();
14 
15     int& operator[](int & key);
16 
17 };
18 
19 
20 int& MySimpleHashmap::operator [](int& key)
21 {
22     return Array[hashcode(key)];
23 }
24 
25 
26 MySimpleHashmap::MySimpleHashmap()
27 {
28     Array=new int[MaxHashSize];
29     
30     for(int i=0;i)
31     {
32         Array[i]=0;
33     }
34 }
35 
36 MySimpleHashmap::~MySimpleHashmap()
37 {
38     delete[] Array;
39     Array=NULL;
40 }
41 
42 int MySimpleHashmap::hashcode(int& key)
43 {
44     while(true)
45     {
46         if(Array[key%MaxHashSize]==0)
47         {
48             return key%MaxHashSize;
49         }
50         else
51         {
52             key++;
53         }
54     }
55 }

main.c

 1 #include "VpoetHashmap.h"
 2 #include 
 3 using namespace std;
 4 
 5 int main()
 6 {
 7     MySimpleHashmap MyHash;
 8     
 9     int key1=15; //hashkey=1
10     int key2=16;  //hashkey=2
11     int key3=9;  //hashkey=2冲突
12     int key4=11;   //hashkey=4
13     int key5=5;    //hashkey=5
14 
15     MyHash[key1]=100;
16     MyHash[key2]=200;
17     MyHash[key3]=300;
18     MyHash[key4]=400;
19     MyHash[key5]=500;
20 
21     cout<<"hash table node1:"<0]<<endl;
22     cout<<"hash table node2:"<1]<<endl;
23     cout<<"hash table node3:"<2]<<endl;
24     cout<<"hash table node4:"<3]<<endl;
25     cout<<"hash table node5:"<4]<<endl;
26     cout<<"hash table node6:"<5]<<endl;
27     cout<<"hash table node7:"<6]<<endl;
28     return 0;
29 }

 

运行截图:

 

 

此外:本文只是粗略的引入了哈希表的原理。里面有几个很重要的地方还没有涉及到:

1.如果不同的的Key的hashcode相同,那么便引起了冲突。如何解决冲突呢。

2.哈希表的初始大小应该怎么取。

3.key映射成索引的hash函数有哪些,这些函数的取法与是否与冲突的次数有关。

4.什么是二次聚集

5.若哈希表填满之后应该怎么扩展哈希表大小

6.装填因子是什么。

这些问题都是在实现hashmap中十分重要的点。



推荐阅读
  • 深入解析Android 4.4中的Fence机制及其应用
    在Android 4.4中,Fence机制是处理缓冲区交换和同步问题的关键技术。该机制广泛应用于生产者-消费者模式中,确保了不同组件之间高效、安全的数据传输。通过深入解析Fence机制的工作原理和应用场景,本文探讨了其在系统性能优化和资源管理中的重要作用。 ... [详细]
  • 本文探讨了 Java 中 Pair 类的历史与现状。虽然 Java 标准库中没有内置的 Pair 类,但社区和第三方库提供了多种实现方式,如 Apache Commons 的 Pair 类和 JavaFX 的 javafx.util.Pair 类。这些实现为需要处理成对数据的开发者提供了便利。此外,文章还讨论了为何标准库未包含 Pair 类的原因,以及在现代 Java 开发中使用 Pair 类的最佳实践。 ... [详细]
  • HashTable与ConcurrentHashMap均可实现HashMap的功能,对外提供了键值对存储的数据结构。但是在内部结构及实现上有何区别,性能上的差异到底在哪里又是如何导致的 ... [详细]
  • 缓存这个东西就是为了提高运行速度的,由于缓存是在寸土寸金的内存里面,不是在硬盘里面,所以容量是很有限的。LRU这个算法就是把最近一次使用时间离现在时间最远的数据删除掉。先说说List:每 ... [详细]
  • 本篇文章给大家分享的是有关Java中怎么对HashMap按键值排序,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话 ... [详细]
  • 01Map集合概述A:Map集合概述:我们通过查看Map接口描述,发现Map接口下的集合与Collection接口下的集合,它们存储数据的形式不同a:Collection中的集合 ... [详细]
  • 手写HashMap,快手面试官直呼内行
    手写HashMap,快手面试官直呼内行-手写HashMap?这么狠,面试都卷到这种程度了?第一次见到这个面试题,是在某个不方便透露姓名的Offer收割机大佬的文章:这……我当 ... [详细]
  • Java面试 HashMap、HashSet源码解析
    本章所有源代码基于JDK1.8版本HashMap和HashSet是JavaCollectionFramework的两个重要成员,其中HashMap是Map接口的常用实现类,Hash ... [详细]
  • hashmap线程不安全允许有null的键和值效率高一点、方法不是Synchronize的要提供外同步有containsvalue和containsKey方法HashMap是Java1 ... [详细]
  • 【转】由HashMap哈希算法引出的求余%和与运算&转换问题
    目录1、引出问题2、结论3、分析过程4、总结回到顶部1、引出问题  在前面讲解HashMap的源码实现时,有 ... [详细]
  • 单片微机原理P3:80C51外部拓展系统
      外部拓展其实是个相对来说很好玩的章节,可以真正开始用单片机写程序了,比较重要的是外部存储器拓展,81C55拓展,矩阵键盘,动态显示,DAC和ADC。0.IO接口电路概念与存 ... [详细]
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 在Java中有多种遍历HashMap的方法,注意Java中所有的Map类型都实现了共有的Map接口,所以接下来方法适用于所有Map(如:HaspMap,TreeMap,Linked ... [详细]
  • 写这篇文章起源于一道面试题,如何将自定义的类对象作为key存储到HashMap中,即考虑怎么判断key的唯一性。首先,我们看以下HashMap中put(…)方法的源码:public ... [详细]
  • HashMap的介绍以及扩容为什么是2的n次幂
    本篇内容介绍了“HashMap的介绍以及扩容为什么是2的n次幂”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带 ... [详细]
author-avatar
黄智铭铭铭铭_216
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有