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

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

数组具有常数复杂度的查找,为什么呢,因为数组是在内存中连续存放,当我们索引某个位置的元素时候根据

索引值自动计算距离数组首元素起始位置的内存间隔。然而对于中间插入和中间删除元素,数组会将待插入位

置后面的原素先整体向后移动一个位置再将元素插入到待插入的位置。所以时间复杂度为O(n)对于大规模的数

组来说,开销是很大的。

然而链表正相反。由于链表是存储在内存中不连续的位置,并且链表之间是通过链表指针链接到一起。前一个元

素保存后一个元素的指针,我们也称之为前一个元素指向后一个元素。当我们在链表中寻找某个元素的时候必须

按照链表指针遍历整个链表,时间复杂度为O(n)但是针对插入很删除来说,我们只需要更改待需要操作的链表元素

的指针即可,时间复杂度为O(1).

那么我们可以不可以把两者结合起来组合成一种新的数据结构呢,这种数据结构即能实现常数复杂度的索引也能

实现常数复杂度的插入和删除。当然哈希表应运而生。

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

插入:当我们插入hashmap['key']=value时,先将key映射为hashcode,然而用hashcode对哈希表长度取模获得索引

位置。然后将值插入到索引位置。(这里可能会存在冲突,即相同的Key的hashcode相同)

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

的值。

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

哈希的原理。

简单hashmap类定义:

 #include<iostream>
using namespace std;
class MySimpleHashmap
{
public:
int *Array;
enum{MaxHashSize=}; int hashcode(int &key); public:
MySimpleHashmap();
~MySimpleHashmap(); int& operator[](int & key); }; int& MySimpleHashmap::operator [](int& key)
{
return Array[hashcode(key)];
} MySimpleHashmap::MySimpleHashmap()
{
Array=new int[MaxHashSize]; for(int i=;i<MaxHashSize;i++)
{
Array[i]=;
}
} MySimpleHashmap::~MySimpleHashmap()
{
delete[] Array;
Array=NULL;
} int MySimpleHashmap::hashcode(int& key)
{
while(true)
{
if(Array[key%MaxHashSize]==)
{
return key%MaxHashSize;
}
else
{
key++;
}
}
}

main.c

 #include "VpoetHashmap.h"
#include <iostream>
using namespace std; int main()
{
MySimpleHashmap MyHash; int key1=; //hashkey=1
int key2=; //hashkey=2
int key3=; //hashkey=2冲突
int key4=; //hashkey=4
int key5=; //hashkey=5 MyHash[key1]=;
MyHash[key2]=;
MyHash[key3]=;
MyHash[key4]=;
MyHash[key5]=; cout<<"hash table node1:"<<MyHash.Array[]<<endl;
cout<<"hash table node2:"<<MyHash.Array[]<<endl;
cout<<"hash table node3:"<<MyHash.Array[]<<endl;
cout<<"hash table node4:"<<MyHash.Array[]<<endl;
cout<<"hash table node5:"<<MyHash.Array[]<<endl;
cout<<"hash table node6:"<<MyHash.Array[]<<endl;
cout<<"hash table node7:"<<MyHash.Array[]<<endl;
return ;
}

运行截图:

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

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

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

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

4.什么是二次聚集

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

6.装填因子是什么。

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

哈希表原理及hashmap简单实现的更多相关文章

  1. 数据结构HashMap哈希表原理分析

    先看看定义:“散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构.也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度. 哈希 ...

  2. 哈希表(hashtable)的javascript简单实现

    javascript中没有像c#,java那样的哈希表(hashtable)的实现.在js中,object属性的实现就是hash表,因此只要在object上封装点方法,简单的使用obejct管理属性的 ...

  3. 【Java源码】集合类-JDK1.8 哈希表-红黑树-HashMap总结

    JDK 1.8 HashMap是数组+链表+红黑树实现的,在阅读HashMap的源码之前先来回顾一下大学课本数据结构中的哈希表和红黑树. 什么是哈希表? 在存储结构中,关键值key通过一种关系f和唯一 ...

  4. C++ 哈希表 (hashtable) 用于保存简单的数据,及数据查找,数据删除

    /*hashtable.h*/ #include<iostream> #include <string> #include<vector> using namesp ...

  5. C语言实现简单的哈希表

    这是一个简单的哈希表的实现,用c语言做的. 哈希表原理 这里不讲高深理论,只说直观感受.哈希表的目的就是为了根据数据的部分内容(关键字),直接计算出存放完整数据的内存地址. 试想一下,如果从链表中根据 ...

  6. 开地址哈希表(Hash Table)的原理描述与冲突解决

    在开地址哈希表中,元素存放在表本身中.这对于某些依赖固定大小表的应用来说非常有用.因为不像链式哈希表在每个槽位上有一个"桶"来存储冲突的元素,所以开地址哈希表需要通过另一种方法来解 ...

  7. C# 哈希表HashTable的简单使用

    本人C#程序菜鸟级别的存在,写博客一方面是为了知识的共享,另一方面也是为了督促自己:大神,可以忽略这篇文文的.废话到此...... 哈希表是可以直接进行访问的数据结构,在形式上是类似字典的.不同的是, ...

  8. 48 容器(七)——HashMap底层:哈希表结构与哈希算法

    哈希表结构 哈希表是由数组+链表组成的,首先有一个数组,数组的每一个位置都用来存储一个链表,链表的基本节点为:[hash值,key值,value值,next],当存入一个键值对时,首先调用hashco ...

  9. 数据结构和算法(Golang实现)(26)查找算法-哈希表

    哈希表:散列查找 一.线性查找 我们要通过一个键key来查找相应的值value.有一种最简单的方式,就是将键值对存放在链表里,然后遍历链表来查找是否存在key,存在则更新键对应的值,不存在则将键值对链 ...

随机推荐

  1. 【hihocoder 1039 字符串消除】模拟

    题目链接:http://hihocoder.com/problemset/problem/1039 题意:给定一个只由{A, B, C}组成的字符串s,长度为n, 故包含n+1个空隙:现要求在某个空隙 ...

  2. 你了解JS执行过程吗?

        正如我们了解的一样,当我们书写了JS程序之后,打开浏览器,我们的代码就可以开始运行了(当然保证你的代码没有问题,才能按照你的预期进行执行).刚才说的是JS执行的一个大的环境,今天我们学习一下, ...

  3. UVA 10285 Longest Run on a Snowboard(记忆化搜索)

    Problem C Longest Run on a Snowboard Input: standard input Output: standard output Time Limit: 5 sec ...

  4. OCR怎么能离开扫描仪呢?

    说起OCR,说来说去就是和各种各样的图片打交道. 所以图片的质量很的关键. 说起图片的质量,不得不提的就是图片的採集. 眼下最靠谱的图像採集来源就是扫描仪. 扫描仪的话就大有说法,最靠谱的扫描仪,扫描 ...

  5. Linux 挂载命令 --mount

    1.挂载光盘命令  mount :  mount [-t vfstype] [-o options] device dir mount [-t 文件系统] [-o 特殊选项] 设备文件名 挂载点 -t ...

  6. C#创建文件夹、文件

    private void CheckCatcheDirectory()//创建文件夹      {          if (!Directory.Exists(xmlFilePath))//xmlF ...

  7. uva 10935 throwing cards away <queue>

    Given is an ordered deck of    n    cards numbered 1 to    n    with card 1 at the top and card    n ...

  8. Qt根据类名创建对象(元对象反射)

    在java语言中,可以使用getObject(String)函数,从类名直接构建新的对象. 而在C++中是没有这种机制的,Qt虽然提供了元对象机制,但只可以获取对象的类名,不能反向构建. 这个问题我在 ...

  9. (原+转)ubuntu16中莫名死机及重新安装显卡驱动

    转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5992693.html 参考网址: http://blog.csdn.net/u012581999/ar ...

  10. 高性能PHP日志插件--Seaslog

    日志系统作为记录系统运行的信息,包括 用户输入,安全日志等,日志系统是不能影响用户的使用. 为什么需要记录日志? 既然日志系统增加了整个系统的开销,为什么我还需要它,这是因为日志能帮我们记录运行的很多 ...