哈希表原理及hashmap简单实现
哈希表也叫做散列表。在各种语言中都有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简单实现的更多相关文章
- 数据结构HashMap哈希表原理分析
先看看定义:“散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构.也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度. 哈希 ...
- 哈希表(hashtable)的javascript简单实现
javascript中没有像c#,java那样的哈希表(hashtable)的实现.在js中,object属性的实现就是hash表,因此只要在object上封装点方法,简单的使用obejct管理属性的 ...
- 【Java源码】集合类-JDK1.8 哈希表-红黑树-HashMap总结
JDK 1.8 HashMap是数组+链表+红黑树实现的,在阅读HashMap的源码之前先来回顾一下大学课本数据结构中的哈希表和红黑树. 什么是哈希表? 在存储结构中,关键值key通过一种关系f和唯一 ...
- C++ 哈希表 (hashtable) 用于保存简单的数据,及数据查找,数据删除
/*hashtable.h*/ #include<iostream> #include <string> #include<vector> using namesp ...
- C语言实现简单的哈希表
这是一个简单的哈希表的实现,用c语言做的. 哈希表原理 这里不讲高深理论,只说直观感受.哈希表的目的就是为了根据数据的部分内容(关键字),直接计算出存放完整数据的内存地址. 试想一下,如果从链表中根据 ...
- 开地址哈希表(Hash Table)的原理描述与冲突解决
在开地址哈希表中,元素存放在表本身中.这对于某些依赖固定大小表的应用来说非常有用.因为不像链式哈希表在每个槽位上有一个"桶"来存储冲突的元素,所以开地址哈希表需要通过另一种方法来解 ...
- C# 哈希表HashTable的简单使用
本人C#程序菜鸟级别的存在,写博客一方面是为了知识的共享,另一方面也是为了督促自己:大神,可以忽略这篇文文的.废话到此...... 哈希表是可以直接进行访问的数据结构,在形式上是类似字典的.不同的是, ...
- 48 容器(七)——HashMap底层:哈希表结构与哈希算法
哈希表结构 哈希表是由数组+链表组成的,首先有一个数组,数组的每一个位置都用来存储一个链表,链表的基本节点为:[hash值,key值,value值,next],当存入一个键值对时,首先调用hashco ...
- 数据结构和算法(Golang实现)(26)查找算法-哈希表
哈希表:散列查找 一.线性查找 我们要通过一个键key来查找相应的值value.有一种最简单的方式,就是将键值对存放在链表里,然后遍历链表来查找是否存在key,存在则更新键对应的值,不存在则将键值对链 ...
随机推荐
- Subsets II 解答
Question Given a collection of integers that might contain duplicates, nums, return all possible sub ...
- 《Algorithms 4th Edition》读书笔记——2.4 优先队列(priority queue)-Ⅴ
命题Q.对于一个含有N个元素的基于堆叠优先队列,插入元素操作只需要不超过(lgN + 1)次比较,删除最大元素的操作需要不超过2lgN次比较. 证明.由命题P可知,两种操作都需要在根节点和堆底之间移动 ...
- Yii2 分页类的扩展和listview引用
Yii2 本身提供了不错分页选项供用户设置,但是实际项目中我们往往需要复杂一些的分页样式,例如下图所示的效果,上下翻页可用和不可用均用图标来替换.
- 用CSS3实现对图片的放大效果
用CSS3对图片放大效果 .right_div .topicons li a:hover img{ -webkit-transform:scale(1.5,1.5); -moz-tra ...
- 在Maven的配置文件中,自定义私有仓库地址和设置下载的jar包的保存位置
在Maven的settings.xml,可以设置Maven的私有仓库的地址,还可以设置所下载jar包在自己电脑的保存地址(默认不设置保存在个人文件夹的.m2文件夹下). 1.设置私有仓库地址: < ...
- [转]Laravel 4之URL生成
Laravel 4之URL生成 http://dingjiannan.com/2013/laravel-url/ 获取当前URL 获取当前URL有两种方式,URL::current()或URL::fu ...
- Linux自动登陆的设置方法
前些天为了实现Linux自动登陆的方法,在网上查了很多资料,发现有不少方法,但网上有些方法的讲解不是特别清楚,或者已经过时.因此,特意整理了一下Linux自动登陆的设置方法.本文的测试环境为Cento ...
- Oracle-nomount/mount/open
通常所说的Oracle Server主要由两个部分组成:Instance和Database.Instance是指一组后台进程(在Windows上是一组线程)和一块共享内存区域:Database是指存储 ...
- 虚拟化之docker安装篇
1,docker pull centos 下载centos镜像 docker search centos 搜索镜像 2,docker images 查看本地镜像 3,do ...
- Query获取值常用
Query获取Select选择的Text和Value:语法解释:1. $("#select_id").change(function(){//code...}); //为Sel ...