精华内容
下载资源
问答
  • 散列函数设计:除留余数法

    千次阅读 2017-02-22 21:36:48
    散列函数设计:除留余数法 转载地址 感谢分享除留余数法介绍 除留余数法此方法为最常用的构造散列函数方法。对于散列表长为m的散列函数公式为:f( key ) = key mod p ( p ≤ m ) mod是取模(求余数)的意思。...

    散列函数设计:除留余数法
    转载地址
    感谢分享

    除留余数法介绍
    除留余数法此方法为最常用的构造散列函数方法。对于散列表长为m的散列函数公式为:

    f( key ) = key mod p ( p ≤ m )
    

    mod是取模(求余数)的意思。事实上,这方法不仅可以对关键字直接取模,也可在折叠、平方取中后再取模。
    一个例子

    很显然,本方法的关键就在于选择合适的p, p如果选得不好,就可能会容易产生同义词。下面我们来举个例子看看:
    

    有一个关键字,它有12个记录,现在我们要针对它设计一个散列表。如果采用除留余数法,那么可以先尝试将散列函数设计为f(key) = key mod 12的方法。比如29 mod 12 = 5,所以它存储在下标为5的位置。
    这里写图片描述
    不过这也是存在冲突的可能的,因为12 = 2×6 = 3×4。如果关键字中有像18(3×6)、30(5×6)、42(7×6)等数字,它们的余数都为6,这就和78所对应的下标位置冲突了。

    甚至极端一些,对于下图的关键字,如果我们让p为12的话,就可能出现下面的情况,所有的关键字都得到了0这个地址数,这未免也太糟糕了点。
    

    这里写图片描述
    但是我们如果不选用p=12来做除留余数法,而选用p=ll,则结果如下:
    这里写图片描述
    这个时候就只有12和144有冲突,相对来说,就要好很多了。
    如何合理选取p值

    使用除留余数法的一个经验是,若散列表表长为m,通常p为小于或等于表长(最好接近m)的最小质数或不包含小于20质因子的合数。
    
    这句话怎么理解呢?要不这样吧,我再举个例子:某散列表的长度为100,散列函数H(k)=k%P,则P通常情况下最好选择哪个呢?A、91 B、93 C、97 D、99
    实践证明,当P取小于哈希表长的最大质数时,产生的哈希函数较好。我选97,因为它是离长度值最近的最大质数。
    
    展开全文
  • 除留余数法学习

    千次阅读 2018-02-07 16:25:23
    除留余数法介绍 除留余数法此方法为最常用的构造散列函数方法。对于散列表长为m的散列函数公式为: f( key ) = key mod p ( p ≤ m ) mod是取模(求余数)的意思。事实上,这方法不仅可以对关键字直接取模,也可...
    除留余数法介绍
    
    除留余数法此方法为最常用的构造散列函数方法。对于散列表长为m的散列函数公式为:
    f( key ) = key mod p ( p ≤ m )
    mod是取模(求余数)的意思。事实上,这方法不仅可以对关键字直接取模,也可在折叠、
    平方取中后再取模。


    一个例子
      很显然,本方法的关键就在于选择合适的p, p如果选得不好,就可能会容易产生同义词。
      下面我们来举个例子看看:
      有一个关键字,它有12个记录,现在我们要针对它设计一个散列表。如果采用除留余数法,
      那么可以先尝试将散列函数设计为f(key) = key mod 12的方法。比如29 mod 12 = 5,所以
      它存储在下标为5的位置。


      不过这也是存在冲突的可能的,因为12 = 2×6 = 3×4。
      如果关键字中有像18(3×6)、30(5×6)、42(7×6)等数字,它们的余数都为6,这就和78所对应
      的下标位置冲突了。


    如何合理选取p值


      使用除留余数法的一个经验是,若散列表表长为m,通常p为小于或等于表长(最好接近m)的最小质数或不包含小于20质因子的合数。


      这句话怎么理解呢?要不这样吧,
      我再举个例子:某散列表的长度为100,散列函数H(k)=k%P,则P通常情况下最好选择哪个呢?
      A、91 B、93 C、97 D、99
     实践证明,当P取小于哈希表长的最大质数时,产生的哈希函数较好。我选97,因为它是离长度值最近的最大质数。
    展开全文
  • . c实现的哈希表。哈希函数采用除留余数法,处理哈希冲突采用链地址法。包含设计文档!在dev c++上验证过。. vs2010 中有代码.有修改过一些BUG.
  • 3.链地址法和开地址法都属于除留余数法 4.留余数法作散列函数优于其他函数 5.分布越均匀,哈希冲突越小,速度越快,开地址法和链地址法的时间复杂度为O(1) 结构体: #define m 13//m个单链表,哈希表的长度 #...

    知识点:

    1.链地址法要优于开地址法

    2.最重要的是插入和查找

    3.链地址法和开地址法都属于除留余数法

    4.除留余数法作散列函数优于其他函数

    5.分布越均匀,哈希冲突越小,速度越快,开地址法和链地址法的时间复杂度为O(1)

    结构体:

    #define m  13//m个单链表,哈希表的长度
    #include <assert.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    typedef struct DataType
    {
    	int key;//关键字项
    	//InfoType otherinfo;//其他数据项
    }DataType;
    
    typedef struct Node
    {
    	DataType data;//数据域
    	struct Node* next;
    }Node;
    
    typedef struct
    {
    	Node* next;//链表的地址
    }HashTable[m];
    

    1.哈希函数

    static int H(int key)
    {
    	return key % m;
    }
    

    2.初始化

    void InitHashTable(HashTable ht)
    {
    	assert(ht != NULL);
    	if (ht == NULL)
    	{
    		return;
    	}
    	for (int i = 0; i < m; i++)
    	{
    		ht[i].next = NULL;
    	}
    }
    

    初始化测试:

    	HashTable ht;
    	InitHashTable(ht);
    

    3.查找

    Node* Search(const HashTable ht, int key)
    {
    	int hi = H(key);//计算key的哈希值
    	for (Node* p = ht[hi].next; p != NULL; p = p->next)
    	{
    		if (p->data.key== key)
    		{
    			return p;
    		}
    	}
    	return NULL;
    }
    

    查找测试:

    HashTable ht;
    	InitHashTable(ht);
    	int arr[16] = { 13,5,7,1,2,9,28,25,6,11,10,15,17,23,34,19 };
    	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    	{
    		Insert(ht, arr[i]);
    	}
    	Show(ht);
    	Node* p;
    	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    	{
    		p = Search(ht, arr[i]);
    		p == NULL ? printf("%d没有找到\n", arr[i]) : printf("%d找到了\n", arr[i]);
    	}
    	p = Search(ht, 100);
    	p == NULL ? printf("%d没有找到\n", 100) : printf("%d找到了\n", 100);
    

    4.插入(将key插入到哈希表ht中)

    bool Insert(HashTable ht, int key)
    {
    	int hi = H(key);
    	if (Search(ht, key) != NULL)//key已经存在
    	{
    		return false;
    	}
    	//插入key
    	Node* p = (Node*)malloc(sizeof(Node));
    	assert(p != NULL);
    	p->data.key = key;
    	//头插
    	p->next = ht[hi].next;
    	ht[hi].next = p;
    	return true;
    }
    

    插入测试:

    	HashTable ht;
    	InitHashTable(ht);
    	int arr[16] = { 13,5,7,1,2,9,28,25,6,11,10,15,17,23,34,19 };
    	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    	{
    		Insert(ht, arr[i]);
    	}
    	Show(ht);
    

    5.打印

    void Show(HashTable ht)
    {
    	for (int i = 0; i < m; i++)
    	{
    		printf("哈希表值为%d的有", i);
    		for (Node* p = ht[i].next; p != NULL; p = p->next)
    		{
    			printf("%d  ", p->data.key);
    		}
    		printf("\n");
    	}
    }
    
    展开全文
  • #define p 13//除留余数法的除数,一般是比m小的最大素数,H(key)=key%p p <= m #define NONE -1//当前哈希表为空 #include <stdio.h> typedef struct Hash { int key;//关键字 //InfoType otherinfo//...

    知识点:

    1.链地址法要优于开地址法

    2.最重要的是插入和查找

    3.链地址法和开地址法都属于除留余数法

    4.除留余数法作散列函数优于其他函数

    5.分布越均匀,哈希冲突越小,速度越快,开地址法和链地址法的时间复杂度为O(1)

    结构体:

    #define m  16//哈希表的长度
    #define  p   13//除留余数法的除数,一般是比m小的最大素数,H(key)=key%p   p <= m
    #define NONE -1//当前哈希表为空
    
    #include <stdio.h>
    
    typedef struct Hash
    {
    	int key;//关键字
    	//InfoType otherinfo//其他数据项
    }Hash,HashTable[m];
    

    1.哈希函数

    //哈希函数:除留余数法
    static int H(int key)
    {
    	return key % p;
    }
    

    2.初始化哈希表

    void  InitHashTable(HashTable ht)
    {
    	for (int i = 0; i < m; i++)
    	{
    		ht[i].key = NONE;
    	}
    }
    

    初始化哈希表测试:

    	//初始化测试:
    	HashTable ht;
    	InitHashTable(ht);
    

    3.//建立哈希表,线性探测法,将key插入到哈希表中,成功返回true,

    bool Insert(HashTable ht, int key)
    {
    	int hi = H(key);
    	if (ht[hi].key == NONE)
    	{
    		ht[hi].key = key;
    		return true;
    	}
    	else
    	{
    		for (int d = 1; d < m; d++)
    		{
    			int newHi = (hi + d) % m;
    			if (ht[newHi].key == key)//key已经存在,不在另外存储
    			{
    				return true;
    			}
    			else if (ht[newHi].key == NONE)
    			{
    				ht[newHi].key = key;
    				return true;
    			}
    		}
    		return false;//存满,没有空位
    	}
    }
    

    插入测试:

    	HashTable ht;
    	InitHashTable(ht);
    	int arr[16] = { 3,5,7,1,2,9,28,25,6,11,10,15,17,23,34,19 };
    	for(int i = 0;i<sizeof(arr)/sizeof(arr[0]);i++)
    	{
    		Insert(ht,arr[i]);
    	}
    	Show(ht);
    

    4.查找,找到了返回下标,没找到返回-1

    int  Search(const HashTable ht, int key)
    {
    	int hi = H(key);
    	for (int i = 0; i < m; i++)
    	{
    		int newHi = (hi + i) % m;
    		if (ht[newHi].key == key)
    		{
    			return newHi;
    		}
    		else if (ht[newHi].key == NONE)
    		{
    			break;
    		}
    	}
    	return -1;
    }
    

    查找测试(找到了返回下标,没找到返回-1):

    HashTable ht;
    	InitHashTable(ht);
    	int arr[16] = { 3,5,7,1,2,9,28,25,6,11,10,15,17,23,34,19 };
    	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    	{
    		Insert(ht, arr[i]);
    	}
    	Show(ht);
    	for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    	{
    		printf("%d :%d ", arr[i], Search(ht, arr[i]));
    	}
    	printf("\n");
    	printf("%d\n", Search(ht, 100));
    

    5.打印

    void Show(HashTable ht)
    {
    	for (int i = 0; i < m; i++)
    	{
    		printf("%d ", ht[i].key);
    	}
    	printf("\n");
    }
    
    展开全文
  • 1、HashMap.java public class HashMap<V> { private Node<V>[] arr; private int len; // 构造方法,初始化底层数组 public HashMap(int len)... // 哈希函数(除留余数法) private int getHash
  • 哈希表的实现 除留余数法

    万次阅读 2017-01-02 11:31:44
    查找有两种方式,比较式查找和计算式查找,而计算式查找则通过哈希表来实现。给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后...这里用除留余数法来构造哈希表和开放地址法中的线性探测再散列来处理不同
  • 除留余数法+ 链地址再散列 #include&lt;bits/stdc++.h&gt; #define HASHSIZE 13 using namespace std; typedef struct node { int num; struct node *next; }NODE; typedef struct hash { NODE *...
  • 散列函数使用除留余数法,散列表长11,即Hash(key)=key%11。用线性探测法解决冲突。要求从文本文件中读取学生信息(相邻数据间用空白符分隔,且姓名不含有空白符),建立散列表,然后输入学生编号,查找...
  • (4)散列函数设计:除留余数法

    千次阅读 2016-02-01 17:50:02
    除留余数法介绍 除留余数法此方法为最常用的构造散列函数方法。对于散列表长为m的散列函数公式为: f( key ) = key mod p ( p ≤ m ) mod是取模(求余数)的意思。事实上,这方法不仅可以对关键字直接...
  • 接下来将利用除留余数法及链地址法实现目标 这里先将链表大小(即链的数量,而非链的长度)定为7(实际应根据数据规模及可接受链长来定,且尽量为质数) 将所有键分别对7取模得:5、0、2、1、5、6、5、6 将键值对...
  • 散列(Hashing)的基本思想:1.计算位置:构造散列函数确定关键词存储位置。2.解决冲突:应用某种...散列函数:除留余数法。//查找打电话最多的人 //冲突处理的方法:分离链接法 //哈希函数:出留余数法 //#incl...
  • 实现哈希表查找(除留余数法

    万次阅读 2017-03-22 17:51:47
    哈希表也称散列表,查找有两种方式,比较式查找和计算式查找,而计算式查找则通过哈希表来实现。给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若...这里用除留余数法来构造哈希表和开放地址法中的线性
  • 1知识点:除留余数法定义hash函数+线性探测法解决hash冲突数据结构实验之查找七:线性之哈希表 Time Limit: 1000MS Memory Limit: 65536KBProblem Description 根据给定的一系列整数关键字和素数p,用除留余数法...
  • 给定一组查找关键字(32,15,7,11,4,28,56,61,79),哈希表长为m=12,请按照除留余数法设计一个哈希函数,设每个记录的查找概率相等。 (1)画出按照线性探测再散列处理冲突得到的哈希表(给出求解过程),并计算等概率...
  • 散列是数据结构中较为重要的内容。两种基本方法之一的链地址法虽稍繁琐,但思路较简单,过程清晰。 散列表(Hash table,也叫哈希...散列函数:除留余数法(取关键字被某个不大于散列表表长m的数p后所得的余数为散...
  • 1知识点:除留余数法定义hash函数+平方探测法解决hash冲突 2反思 & 思考: hash冲突数据: 4 5 1 6 11 16数据结构实验之查找五:平方之哈希表 Time Limit: 400MS Memory Limit: 65536KBProblem Description ...
  • Hash函数计算--常用方法之--除留余数法:假设哈希表长为m,p为小于等于m的最大素数,则哈希函数为h(k)=k % p ,其中%为模p取余运算。例如,已知待散列元素为(18,75,60,43,54,90,46),表长m=10,p=7,则...
  • //除留余数法 } bool InsertHash(HashTable *H,int key) { if(H->count == m) return false; int addr = Hash(key); while(H->elem[addr] != NULLKEY) { if(H->elem[addr] == key) return false; addr = (addr+1) %...
  • 直接定址 直接定址是以数据元素关键字k本身或它的线性函数作为它的哈希地址,即:H(k)=k或H(k)=a×k+b;(其中a,b为常数) 例1,有一个人口统计表,记录了从1岁到100岁的人口数目,其中年龄作为关键字,哈希...
  • #include<iostream> #define MaxSize 100 #define NULLKEY -1//define empty keyword value(定义空关键字值) using namespace std; typedef struct { ...//keyword(关键字) ...//number of explorations(探索次数) ...
  • Hash(除留余数法+链地址法)

    千次阅读 2019-04-30 19:08:38
    //哈希函数:留余数 //处理冲突:链地址 #include<stdio.h> #include<stdlib.h> #include<algorithm> using namespace std; const int N=10; struct Node{ int num; Node *next; }; ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,950
精华内容 3,180
关键字:

除留余数法