哈希表

原创 2012年03月27日 20:11:47

哈希表是种数据结构,它可以提供快速的插入操作和查找操作。第一次接触哈希表时,它的优点多得让人难以置信。不论哈希表中有多少数据,插入和删除(有时包括侧除)只需要接近常量的时间即0(1)的时间级。实际上,这只需要几条机器指令。

  对哈希表的使用者一一人来说,这是一瞬间的事。哈希表运算得非常快,在计算机程序中,如果需要在一秒种内查找上千条记录通常使用哈希表(例如拼写检查器)哈希表的速度明显比树快,树的操作通常需要O(N)的时间级。哈希表不仅速度快,编程实现也相对容易。

  哈希表也有一些缺点它是基于数组的,数组创建后难于扩展某些哈希表被基本填满时,性能下降得非常严重,所以程序虽必须要清楚表中将要存储多少数据(或者准备好定期地把数据转移到更大的哈希表中,这是个费时的过程)。

  而且,也没有一种简便的方法可以以任何一种顺序〔例如从小到大〕遍历表中数据项。如果需要这种能力,就只能选择其他数据结构。

然而如果不需要有序遍历数据,井且可以提前预测数据量的大小。那么哈希表在速度和易用性方面是无与伦比的。

 

哈希表算法-哈希表的概念及作用

  一般的线性表,树中,记录在结构中的相对位置是随机的,即和记录的关键字之间不存在确定的关系,因此,在结构中查找记录时需进行一系列和关键字的比较。这一类查找方法建立在“比较“的基础上,查找的效率依赖于查找过程中所进行的比较次数。

  理想的情况是能直接找到需要的记录,因此必须在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使每个关键字和结构中一个唯一的存储位置相对应。

哈希表最常见的例子是以学生学号为关键字的成绩表,1号学生的记录位置在第一条,10号学生的记录位置在第10条...

如果我们以学生姓名为关键字,如何建立查找表,使得根据姓名可以直接找到相应记录呢?

 

哈希表算法

 

用上述得到的数值作为对应记录在表中的位置,得到下表:

哈希表算法

 

上面这张表即哈希表。

如果将来要查李秋梅的成绩,可以用上述方法求出该记录所在位置:

李秋梅:lqm 12+17+13=42 取表中第42条记录即可。

问题:如果两个同学分别叫 刘丽 刘兰 该如何处理这两条记录?

这个问题是哈希表不可避免的,即冲突现象:对不同的关键字可能得到同一哈希地址。

 

 

 哈希表算法-哈希表的构造方法

1、直接定址法

例如:有一个从1到100岁的人口数字统计表,其中,年龄作为关键字,哈希函数取关键字自身。

           但这种方法效率不高,时间复杂度是O(1),空间复杂度是O(n),n是关键字的个数

 

哈希表算法

 

2、数字分析法

有学生的生日数据如下:

年.月.日

75.10.03
75.11.23
76.03.02
76.07.12
75.04.21
76.02.15
...

经分析,第一位,第二位,第三位重复的可能性大,取这三位造成冲突的机会增加,所以尽量不取前三位,取后三位比较好。

3、平方取中法

取关键字平方后的中间几位为哈希地址

4、折叠法

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

例如:每一种西文图书都有一个国际标准图书编号,它是一个10位的十进制数字,若要以它作关键字建立一个哈希表,当馆藏书种类不到10,000时,可采用此法构造一个四位数的哈希函数。如果一本书的编号为0-442-20586-4,则:

 

哈希表算法

 

5、除留余数法

取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。

H(key)=key MOD p (p<=m)

6、随机数法

选择一个随机函数,取关键字的随机函数值为它的哈希地址,即

H(key)=random(key) ,其中random为随机函数。通常用于关键字长度不等时采用此法。

5、除留余数法

取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。

H(key)=key MOD p (p<=m)

6、随机数法

选择一个随机函数,取关键字的随机函数值为它的哈希地址,即

H(key)=random(key) ,其中random为随机函数。通常用于关键字长度不等时采用此法。

5、除留余数法

取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。

H(key)=key MOD p (p<=m)

6、随机数法

选择一个随机函数,取关键字的随机函数值为它的哈希地址,即

H(key)=random(key) ,其中random为随机函数。通常用于关键字长度不等时采用此法。

 

哈希表算法-处理冲突的方法


 

 

如果两个同学分别叫 刘丽 刘兰,当加入刘兰时,地址24发生了冲突,我们可以以某种规律使用其它的存储位置,如果选择的一个其它位置仍有冲突,则再选下一个,直到找到没有冲突的位置。选择其它位置的方法有:

1、开放定址法

Hi=(H(key)+di) MOD m i=1,2,...,k(k<=m-1)

其中m为表长,di为增量序列

如果di值可能为1,2,3,...m-1,称线性探测再散列。

如果di取值可能为1,-1,2,-2,4,-4,9,-9,16,-16,...k*k,-k*k(k<=m/2)

称二次探测再散列

如果di取值可能为伪随机数列。称伪随机探测再散列。

例:在长度为11的哈希表中已填有关键字分别为17,60,29的记录,现有第四个记录,其关键字为38,由哈希函数得到地址为5,若用线性探测再散列,如下:

 

哈希表算法

 

2、再哈希法

当发生冲突时,使用第二个、第三个、哈希函数计算地址,直到无冲突时。缺点:计算时间增加。

3、链地址法

将所有关键字为同义词的记录存储在同一线性链表中。

 
哈希表算法

 

4、建立一个公共溢出区

假设哈希函数的值域为[0,m-1],则设向量HashTable[0..m-1]为基本表,另外设立存储空间向量OverTable[0..v]用以存储发生冲突的记录。

以下为开方定址法的C++实现代码:

#include<iostream>
using namespace std;
int Hash(int key,int length)
{
	return (key*3)%length;	
}
typedef struct element
{
	int key;
	int state;
}Element;
class HashTable
{
private:
	Element * m_element;
	int m_size;
	int m_nodenum;
public:
	HashTable(int a):m_size(a)
		{
		this->m_nodenum=0;
		m_element=new Element[a];
		for(int i=0;i<a;i++)
			{
			m_element[i].key=0;
			m_element[i].state=0;
			}
		}
	~HashTable()
		{
		delete []m_element;
		}
	bool Insert(int key);
	bool Search(int item,int &pos);
	int GetSize()
		{
		return this->m_nodenum;
		}
	void Display()
		{
		if(this->m_nodenum==0)
			{
			cout<<"the table is empty!"<<endl;
			return ;
			}
		for(int i=0;i<this->m_size;i++)
			{
			if(this->m_element[i].state==1)
				{
				cout.width(4);
				cout<<this->m_element[i].key;
				cout<<"                         ";
				cout.width(3);
				cout<<i<<endl;
				}
			}
		}

};

bool HashTable::Insert(int key)
	{
	if(this->m_nodenum==this->m_size)
		{
		cout<<"the table is full!"<<endl;
		return 0;
		}
	int hashValue=Hash(key,this->m_size);
	for(int i=0;i<this->m_size;i++)
		{
		if(m_element[hashValue].state==0)
			{
			this->m_element[hashValue].key=key;
			this->m_nodenum++;
			this->m_element[hashValue].state=1;
			cout<<"Insert Value Success!The value is:"<<key<<";the addr is:"<<hashValue<<endl;
			return 1;
			}
		else if(m_element[hashValue].state==1)
			{
			hashValue=(hashValue+i)%(this->m_size);
			}
		}
	cout<<"Insert filled !"<<endl;
	return 0;
	
	}
bool HashTable::Search(int item, int &pos)
	{
	if(this->m_nodenum==this->m_size)
		{
		cout<<"the table is full!"<<endl;
		pos=-1;
		return 0;
		}
	int keyvalue=Hash(item,this->m_size);
	for(int i=0;i<this->m_size;i++)
		{
		if(this->m_element[keyvalue].state==1&&this->m_element[keyvalue].key==item)
			{
			cout<<"find the element "<<item<<" and the position is "<<i<<endl;
			pos=keyvalue;
			return 1;
			}
		else
			keyvalue=(keyvalue+i)%(this->m_size);
		}
	cout<<"can't find the value!"<<endl;
	pos=-1;
	return 0;
	}
int main()
{
    int array[]={22, 41, 53, 46, 30,13, 01,67};
    HashTable hTable(11);
    for(int i =0;i < 8;i++)
    hTable.Insert(array[i]);
    hTable.Display();
	int pos;
	hTable.Search(41,pos);
	cout<<"the pos is "<<pos<<endl;
    return 0;
}


 

 

哈希表的创建

在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使每个关键字和表中唯一的存储位置相对应,称这个对应关系f为哈希(散列)函数,根据这个思想建立的表为哈希表。   若key1≠key2, 而f...
  • sanqima
  • sanqima
  • 2015年10月06日 22:28
  • 4346

数据结构实验:哈希表(SDUT 1480)

数据结构实验:哈希表 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述  在n个数中,找出出现次数最多那个数字...
  • u013486414
  • u013486414
  • 2014年06月14日 22:46
  • 778

数据结构例程——哈希表及其运算的实现

本文是[数据结构基础系列(8):查找]中第11课时[哈希表——散列结构]和第12课时[哈希表的运算]的例程。#include #define MaxSize 100 //定义最大哈希...
  • sxhelijian
  • sxhelijian
  • 2015年11月28日 16:24
  • 4025

使用哈希表解决几个常见算法题

简介哈希表是一种非常常见的KV型的数据结构,他的搜索效率十分高,时间复杂度通常都在O(N)。在C++11之后,引入了容器 unordered_map,它的底层实现就是哈希表,所以我们在需要使用哈希表的...
  • MBuger
  • MBuger
  • 2017年06月04日 15:43
  • 1277

基于哈希表的通讯录

1.需求分析   本演示程序用C语言编写,完成哈希表的生成,电话号码的插入、以及查找等功能。   (1)按提示输入相应的联系人的相关资料;   (2)以相应的输出形式输出所存储的的联系人的资料;...
  • qq_38116774
  • qq_38116774
  • 2018年01月06日 10:43
  • 144

哈希表类模板的设计与实现

template struct HashTableNode { T varValue; N varName; HashTableNode *next; N Scope; N alias; ...
  • judyge
  • judyge
  • 2015年04月16日 08:55
  • 339

老生常谈——哈希表

哈希表也叫做散列表,是一种根据关键码值(key value)来进行直接访问的数据结构。...
  • dd864140130
  • dd864140130
  • 2015年02月27日 02:22
  • 1424

数据结构复习一:哈希表的总结

昨天复习了一下哈希表,今天来总结一下。哈希表概述哈希表,是根据关键码值(key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录。由于可以根据哈希函数直接得...
  • FreeeLinux
  • FreeeLinux
  • 2017年02月01日 16:06
  • 755

简单介绍哈希表作用及程序举例

转自:http://blog.csdn.net/songzi1111/article/details/10985429 转自:http://blog.csdn.net/yleek/article/d...
  • mark20170902
  • mark20170902
  • 2016年07月15日 10:07
  • 434

java中哈希表及其应用详解

http://blog.csdn.net/u010297957/article/details/51974340 什么是哈希表 数组和向量都可以存储对象,但对象的存储位置是随机的,也就是说对象...
  • xiaoxik
  • xiaoxik
  • 2017年07月10日 15:52
  • 593
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:哈希表
举报原因:
原因补充:

(最多只允许输入30个字)