body, table{font-family: 微软雅黑; font-size: 13.5pt}
table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;}
th{border: 1px solid gray; padding: 4px; background-color: #DDD;}
td{border: 1px solid gray; padding: 4px;}
tr:nth-child(2n){background-color: #f8f8f8;}

  散列技术是在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使得每个关键字key对应一个存储位置f(key),adr = f(key)。查找时,根据这个确定的对应关系找到给定值key的映射f(key),若查找集合中存在这个记录,则必定在f(key)的位置上。
  这里我们把这种对应关系f称为散列函数,又称为哈希函数(Hash).按这个思想,采用散列技术将记录存储在一块连续的存储空间中,这块连续的存储空间称为散列表或哈希表(Hash table)。关键字对应的记录存储位置称为散列地址。

散列技术既是一种存储方法,也是一种查找方法。
散列技术最适合求解的问题是查找与给定值相等的记录。

散列函数设计原则:简单、均匀、存储利用率高

两个关键字 key1 ≠ key2,但是却有 f(key1) ≠ f(key2),这种现象我们称为冲突(collision),并把key1和key2称为这个散列函数的同义词(synonym)。

散列函数设计原则:
  计算简单: 散列函数的计算时间不应该超过其他查找技术与关键字比较的时间。
  散列地址分布均匀:尽量让散列地址均匀地分布在存储空间中,这样可以保证存储空间的有效利用,并减少为处理冲突而耗费的时间。
直接定址法 f(key) = a * key + b(a、b为常数)
  取关键字的某个线性函数值为散列地址。(这样的散列函数简单、均匀、不会产生冲突;需要事先知道关键字的分布情况,适合查找表较小且连续的情况,较少使用)
数字分析法
  抽取关键字的一部分来计算散列函数位置的方法。适合处理关键字位数比较大的情况,(如果事先知道关键字的分布且关键字的若干位分布比较均匀,就可以考虑用这个方法。)
平方取中法
  计算关键字的平方,再取中间几位做为关键字。eg:1234,平方1522756,取中间3为227为关键字。(平方取中法比较适合不知道关键字的分布,而位数又不是很大的情况。)
折叠法
  将关键字从左到右分割成位数相等的几部分,然后将这几部分叠加求和,并按散列表表长,取后几位作为散列表地址。(折叠法事先不需要知道关键字的分布,适合关键字位数较多的情况。)
除留余数法
  此方法为最常用的构造散列函数的方法。对于散列表长为m的散列函数公式为:f(key) = key mod p(p≤m)
这种方法不仅可以对关键字直接取模,也可在折叠、平方取中后再取模。**散列表长为m,通常p为小于或等于表长(最好接近m)的最小质数或不包含小于20质因子的合数。
随机数法
  选择一个随机数,取关键字的随机函数值为它的散列地址,也就是 f(key) = random(key)。这里random是随机函数。(当关键字的长度不等时,采用这个方法构造散列函数是比较合适的)

选择散列函数应该考虑事项:
1、计算散列地址所需时间
2、关键字的长度
3、散列表的大小
4、关键字的分布情况
5、记录查找的频率

处理散列冲突的方法
开放定址法
  一旦发生了冲突,就去寻找下一个空的散列地址,知道散列表足够大,空的散列表地址总能找到,并将记录存入。这种解决冲突的开放定址发称为线性探测法。
  fi(key) = (f(key) + di) MOD m (di = 1,2,3,...,m-1)
在发生冲突进行重新定址的过程中会导致后面不是同义词的关键字( f(keyi) ≠ f(key2) )争夺一个地址的情况,这种现象为堆积。
  线性探测都是发生冲突后加上一个di然后取余数来寻找下一个空间地址,如果发生冲突的位置之前就有一个空位置,要找到这个空位置要循环效率就很低
  fi(key) = (f(key) + di) MOD m (di = 1^2,-1^2,2^2,...,q^2,-q^2,q≤m/2)
增加平方运算的目的是为了不让关键字都聚集在某一块区域,这种方法叫做二次探测法。
   在冲突时,对于位移量di采用随机函数计算得到。
  fi(key) = (f(key) + di) MOD m (di 是一个伪随机数列) 。 伪随机,只要随机种子相同,每次得到的数列都会是相同的。这就是随机探测法
再散列函数法
  fi(key) = RHi(key)  (i=1,2,...,k)
其中RHi就是不同的散列函数,每当发送冲突时,就换一个散列函数计算,总有一个可以解决冲突
链地址法:将所有关键字为同义词的记录存储在一个单链表中,这种链表叫做同义词子表,使用除留余数法,就不存在冲突的问题了,只是在链表中增加一个结点。
公共溢出区法:
  对所有冲突的关键字建立一个公共溢出区来存放
   
#include<iostream>
#include<stdlib.h>
#define max  ~( 1<<(sizeof(int)*8-1) )
using namespace std;
//散列函数采用除留余数法
//冲突解决采用开放定址法的线性探测法
int hashFunc(int key,int length);
int initHashTable(int* hashTable,int length);  //成功返回0,失败返回-1
int hashInsert(int* hashTable,int key,int length);   //成功返回0,失败返回-1
static enum status{failture=-1,success=0} flag;
int hashSearch(int*hashTable,int key,int length); 
void test();
int main()
{
        test();
        system("pause");
}
int initHashTable(int* hashTable,int length)
{
        if(nullptr==hashTable || length<=0)
                return -1;
        for(int idx=0;idx!=length;++idx)
        {
                hashTable[idx] = max;
        }
        return 0;
}
int hashFunc(int key,int length)
{
        if(key==max||length<=0)
                return -1;
        return key % length;    //除留余数
}
int hashInsert(int* hashTable,int key,int length)
{
        if(nullptr==hashTable||length<=0)
                return -1;
        int hashAddr = hashFunc(key,length);
        if(-1==hashAddr)
                return -1;
        for(int idx=0;idx!=length;++idx)    //循环,最大哈希表长度
        {
                if(hashTable[hashAddr]!=max)    //冲突
                        hashAddr = (hashAddr+1) % 12;   //开放定址法的线性探测法,查找下一个可存放数据的空间
                else
                        break;
        }
        if(max==hashTable[hashAddr])
        {
                hashTable[hashAddr] = key;
                return 0;
        }
        return -1;
}
void test()
{
        int arr[12] = {12,67,56,16,25,37,22,29,15,47,48,34};
        int* hashTable = new int[12]();
        int ret = initHashTable(hashTable,12);
        if(-1==ret)
                cout<<"initHashTable fail!"<<endl;
        cout<<"哈希表待插入元素:";
        for(int idx=0;idx!=12;++idx)
        {
                cout<<arr[idx]<<" ";
                hashInsert(hashTable,arr[idx],12);
        }
        cout<<endl;
        cout<<"哈希表:";
        for(int idx=0;idx!=12;++idx)
        {
                cout<<hashTable[idx]<<" ";
        }
        cout<<endl;
        cout<<"对应插入元素序列在哈希表查找元素:";
        for(int idx=0;idx!=12;++idx)
        {
                int ret = hashSearch(hashTable,arr[idx],12);
                if( ret==-1 && flag == failture)
                {
                        cout<<"search "<<arr[idx]<<" fail"<<endl;
                }
                cout<<hashTable[ret]<<" ";
        }
        cout<<endl;
        cout<<"查找1:"<<endl;
        int rett = hashSearch(hashTable,1,12);
        if( rett==-1 && flag == failture)
        {
                cout<<"search "<<1<<" fail"<<endl;
                return ;
        }
        cout<<hashTable[rett]<<endl;

}
int hashSearch(int*hashTable,int key,int length)
{
        flag = success;
        if(nullptr==hashTable||length<=0)
        {
                flag = failture;
                return -1;
        }
        int hashAddr = hashFunc(key,length);
        while(key!=hashTable[hashAddr])
        {
                hashAddr = (hashAddr+1) % length;
                if(max==hashTable[hashAddr] || hashAddr == hashFunc(key,length))  //如果探测到下一个地址为空,还没有找到,或者循环找了一遍又回到最开始的hashAddr
                {
                        flag = failture;
                        return -1;
                }
        }
        return hashAddr;
}

哈希表概念和实现,C/C++实现的更多相关文章

  1. 哈希表(hash table)基础概念

    哈希是什么 引入:我们在学习数组的时候,使用数组元素的下标值即可访问到该元素,所花费的时间是O(1),与数组元素的个数n没有关系,这就是哈希方法的核心思想. 哈希方法:以关键值K为自变量,通过一定的函 ...

  2. 什么叫哈希表(Hash Table)

    散列表(也叫哈希表),是根据关键码值直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度.这个映射函数叫做散列函数,存放记录的数组叫做散列表. - 数据结构 ...

  3. Berkeley DB的数据存储结构——哈希表(Hash Table)、B树(BTree)、队列(Queue)、记录号(Recno)

    Berkeley DB的数据存储结构 BDB支持四种数据存储结构及相应算法,官方称为访问方法(Access Method),分别是哈希表(Hash Table).B树(BTree).队列(Queue) ...

  4. 从HashMap透析哈希表

    ##扯数据结构 先看一下哈希表的概念: 哈希表是一种数据结构,它可以提供快速的插入操作和查找操作.第一次接触哈希表,他会让人难以置信,因为它的插入和删除.查找都接近O(1)的时间级别.用哈希表,很多操 ...

  5. 哈希表的C++实现(转)

    哈希表的几个概念: 映像:由哈希函数得到的哈希表是一个映像. 冲突:如果两个关键字的哈希函数值相等,这种现象称为冲突. 处理冲突的几个方法: 1.开放地址法:用开放地址处理冲突就是当冲突发生时,形成一 ...

  6. 散列表 (Hash table,也叫哈希表)

    散列表是根据关键字(Key value)而直接访问在内存存储位置的数据结构.也就是说,它通过把键值通过一个函数的计算,映射到表中一个位置来访问记录,这加快了查找速度.这个映射函数称做散列函数,存放记录 ...

  7. C#中哈希表与List的比较

    简单概念 在c#中,List是顺序线性表(非链表),用一组地址连续的存储单元依次存储数据元素的线性结构. 哈希表也叫散列表,是一种通过把关键码值映射到表中一个位置来访问记录的数据结构.c#中的哈希表有 ...

  8. 哈希,哈希表,哈希Map

    数组: 数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二分查找时间复杂度小,为O(1):数组的特点是:寻址容易,插入和删除困难: 链表: 链表存储区间离散,占用内存比较宽松,故空间复杂 ...

  9. perl5 第九章 关联数组/哈希表

    第九章 关联数组/哈希表 by flamephoenix 一.数组变量的限制二.定义三.访问关联数组的元素四.增加元素五.创建关联数组六.从数组变量复制到关联数组七.元素的增删八.列出数组的索引和值九 ...

随机推荐

  1. 第 3 章 镜像 - 013 - Dockerfile 构建镜像

    第一个 Dockerfile FROM ubuntu RUN apt-get update && apt-get install -y vim 运行 docker build 命令构建 ...

  2. 安卓中使用OkHttp发送数据请求的两种方式(同、异步的GET、POST) 示例-- Android基础

    1.首先看一下最终效果的截图,看看是不是你想要的,这个年代大家都很忙,开门见山很重要! 简要说下,点击不同按钮可以实现通过不同的方式发送OkHttp请求,并返回数据,这里请求的是网页,所以返回的都是些 ...

  3. BGP - 4,BGP的三张表

    1,BGP的三张表      邻居表(adjancy table)      BGP表(forwarding database):BGP默认不做负载均衡,会选出一条最优的,放入路由表      路由表 ...

  4. flex自定义preloader预加载进度条

    flex默认的preloader已经很不错了,可是有时候还是需要自定义的.   需要在要出现自定义预加载的程序的<mx:Application>标签里加入preloader="& ...

  5. re正则表达式方法

    目录 1.python正则匹配 1.1 re.search 正则表达式 1.2 re.match() 正则表达式 1.3 re.match与re.search的区别 1.4 检索和替换 1.5 正则表 ...

  6. jenkins 构建selenium python (浏览器驱动是chromedriver)的解决方法

    1.在chrome浏览去中输入chrome://version  查看chrome 的安装位置 2.将chromedriver 驱动添加到可执行文件路径中 3.在Jenkins中 的系统设置中-环境变 ...

  7. Activiti搭建

    Activiti搭建 前期准备: JDK+Eclipse+Tomcat+Maven的安装与配置 参考:http://blog.csdn.net/zhshulin/article/details/307 ...

  8. 使用navigator.userAgent.toLowerCase()判断移动端类型

    使用navigator.userAgent.toLowerCase()判断移动端类型 判断设备,区分Android,iphone,ipad和其它 var ua = navigator.userAgen ...

  9. python BeautifulSoup 介绍--安装

    Python中,专门用于HTML/XML解析的库: 特点是: 即使是有bug,有问题的html代码,也可以解析. BeautifulSoup主要有两个版本 BeautifulSoup 3 之前的,比较 ...

  10. Git Diff 格式分析

    参考: http://stackoverflow.com/questions/2529441/how-to-read-the-output-from-git-diff https://www.git- ...