散列之再散列

【0】README

0.1)本文描述总结于 数据结构与算法分析, 但源代码为原创;
0.2)为什么写这篇博文? 再散列的代码实现 包括了 解决冲突的方法实现;很有代表性;(本源代码采用的解决冲突方法是 平方探测法)


【1】问题+解决方法

1.0)开放定址法定义:它是一种不用链接解决冲突的方法:如果有冲突发生, 那么就要尝试选择另外的单元,知道找出空的单元为止;
这里写图片描述
1.1)出现的问题:对于使用平方探测的开放定址散列法,如果表的元素填的太满, 那么操作的运行时间将开始消耗过长,且 insert 操作可能失败, 这可能发生在有 太多的移动和插入混合的场合;
1.2)解决方法:建立另外一个大约两倍大的表(使用一个相关的新散列函数),扫描整个原始散列表,计算每个元素的新散列值并将其插入到新表中;
1.3)看个荔枝:

  • 1)将元素13, 15, 24 和 6 插入到大小为 7 的开放定址散列表中:散列函数是 h(X) = X mod 7;设使用线性探测方法解决冲突问题, 插入结果得到的散列表表示在下图中:
    这里写图片描述
  • 2)如果将 23 插入表中, 那么从下图可以看到, 插入后的表将有超过70% 的单元是满的,因为表填得过满, 所以我们建立一个新表;该表的大小为 17, 因为17是原表大小两倍后的第一个素数;新的散列函数为 h(X) = X mod 17;扫描原来的表, 并将元素 6, 15, 23 , 24 以及13 插入到新表中, 如下下图所示:
    这里写图片描述
    这里写图片描述

【2】再散列

2.1)定义:以上整个操作就叫做再散列;显然这是一种非常昂贵的操作, 其运行时间为 O(N),因为有N 个元素要再散列而表的大小约为2N, 不过由于不是经常发生,所以实际效果根本不是那么差;
2.2)再散列的实现:
再散列可以用平方探测以多种方法实现:

  • 1)一种做法是:只要表满到一半就再散列;
  • 2)另一个极端方法是:只有当插入失败时才再散列;
  • 3)第3种方法即途中策略:当表到达某一个装填因子时进行再散列。由于随着装填因子的增加,表的性能有所下降, 因此,以好的截止手段实现的第三种策略, 可能是最好的策略;

2.3)再散列的作用:
再散列就是把 程序员从表大小的担心中解放出来, 这一点很重要, 因为在复杂的程序中散列表不能够做得任意地大;


【3】源代码+打印结果

3.1)解决冲突的方法:我们采用的是平方探测,1,-1,4,-4,……
3.2)Attention)在 “再散列”的代码中,我们为 HashTable 添加另一个 capacity 成员,用于和 size 相除构成 装填因子,以便于判断该装填因子是否超出某个值;
3.3)downlaod source code : https://github.com/pacosonTang/dataStructure-algorithmAnalysis/blob/master/chapter5/p123_rehash.c
3.4)source code at a glance :

#include <stdio.h>
#include <malloc.h>
#include <math.h>#define ElementType int
#define Error(str) printf("\n error: %s \n",str)   struct HashTable;
typedef struct HashTable *HashTable;
struct HashEntry;
typedef struct HashEntry *HashEntry;
typedef HashEntry EntryArray;HashTable initHashTable(int size);
int find(ElementType key, HashTable ht);
HashTable insert(ElementType key, HashTable ht);enum EntryType {Legitimate, Empty, Deleted};struct HashEntry
{ElementType key;enum EntryType status;
};struct HashTable
{EntryArray entryArray;int capacity;int size;
};//judge whether the value is prime or not, also 1  or 0
int isPrime(int value)
{int temp;int flag;flag = 1;temp = 2;while(temp < sqrt(value)){if(value % temp == 0)flag = 0;temp++;}return flag;
}// compute the minial prime greater than the value
int nextPrime(int value)
{               value++;while(1){if(isPrime(value))break;value++;}return value;
} // hash function
int hashFunc(int key, int capacity)
{return key % capacity;
}// the rehash function to expand hash table capacity upto twice capcity
HashTable rehashFunc(HashTable ht)
{int capacity;int oldCapacity;int i;EntryArray temp;temp = ht->entryArray;oldCapacity = ht->capacity;capacity = nextPrime(ht->capacity * 2);ht = initHashTable(capacity);for(i = 0; i < oldCapacity; i++)if(temp[i].status == Legitimate)insert(temp[i].key, ht);free(temp);return ht;
}// initializing HashTable with given size and the table size should be a prime number
HashTable initHashTable(int capacity)
{HashTable ht;   int i;ht = (HashTable)malloc(sizeof(struct HashTable)); // allocate memory for HashTableif(!ht) {Error("out of space, from func initHashTable");return NULL;}ht->capacity = capacity; // the table capacity should be a prime numberht->size = 0; // the number the hash table stores elementht->entryArray = (HashEntry)malloc(capacity * sizeof(struct HashEntry)); // allocate memory for entry arrayfor(i = 0; i < capacity; i++) ht->entryArray[i].status = Empty;return ht;
}// insert the entry with value key into the Hash Table
HashTable insert(ElementType key, HashTable ht)
{int index;double loadFactor = 0.7; // let the load facotr equals to 0.7, of cource load factor depends on your minddouble temp;index = find(key, ht);if(ht->entryArray[index].status != Legitimate){ht->entryArray[index].status = Legitimate;ht->entryArray[index].key = key;ht->size++;// judge whether the load facotr is greater than the certain valuetemp = (double) ht->size / ht->capacity;        if(temp >= loadFactor)ht = rehashFunc(ht);}return ht;
}// find the index the entry with key should be placed into 
int find(ElementType key, HashTable ht) // find the hash entry with value key 
{int index;  int collisionIndex; int minus = -1;int temp;collisionIndex = 0;index = hashFunc(key, ht->capacity); // call the first hash function for allocating empty position for storing the key  temp = index;while(ht->entryArray[temp].status != Empty && ht->entryArray[temp].key != key ) // adopting square probing{if(minus == -1)collisionIndex++;minus *= -1;temp = collisionIndex * collisionIndex * minus;         temp = (index + temp) % ht->capacity;}       return temp;
}void printHashTable(HashTable ht)
{ElementType key;int i;  if(!ht)Error("printing execution failure, for hashtable is null, from func printHashTable");   i = 0;while(i < ht->capacity) {printf("\n\t index[%d] = ", i);key = ht->entryArray[i].key;    if(ht->entryArray[i].status == Legitimate)printf("%d", key);          elseprintf("NULL");printf("  ");       i++;}printf("\n\n");
}int main()
{HashTable ht = NULL;int dataSize = 4;int i;ElementType key[] = {13, 15, 24, 6};printf("\n\t=== test for rehashing the hash table with load factor 0.7 and capacity 7, and adopting square probing ===\n");ht = initHashTable(7);// the size of HashTable must be prime number;printf("\n\t=== test for inserting 13, 15, 24, 6 in turn into the hash table  ===\n");for(i = 0; i< dataSize; i++)    ht = insert(key[i], ht);    printHashTable(ht);     printf("\n\t=== test for inserting 23 into the hash table  ===\n");ht = insert(23, ht);    printHashTable(ht);     printf("\n\t=== test for inserting 40 into the hash table  ===\n");ht = insert(40, ht);    printHashTable(ht);     return 0;
}

3.5)printing result
这里写图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/332001.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

激活策略 查询_5个提问,详细介绍北极星指标的策略框架

北极星指标&#xff08;North Star Metric&#xff09;已经逐渐成为许多公司指导产品发展的重要指标&#xff0c;本文通过五个设问和多个行业案例&#xff0c;系统性地介绍北极星指标这类产品策略框架。如今有非常多的人在谈论和使用北极星指标&#xff08;North Star Metric&a…

变色龙嗅探卡功能_变色龙功能

变色龙嗅探卡功能在《神秘博士》中&#xff0c;卡梅利恩&#xff08;Kamelion&#xff09;角色是一个可以采取任何形式的机器人。 据称&#xff0c;他们使用的物理道具非常麻烦&#xff0c;只有其创建者才能理解&#xff0c;而该创建者并没有帮助纠正它。 因此&#xff0c;Cha…

老人与海好词100英文带翻译_《老人与海》经典语录(英文+译文)

《老人与海》是海明威于1951年在古巴写的一篇中篇小说&#xff0c;于1952年出版。是海明威最著名的作品之一。它围绕一位老年古巴渔夫&#xff0c;与一条巨大的马林鱼在离岸很远的湾流中搏斗而展开故事的讲述。它奠定了海明威在世界文学中的突出地位&#xff0c;这篇小说相继获…

java多态+多态中隐含的问题

【0】RAEDME 0.1&#xff09;本文总结于 core java volume 1&#xff0c; 感觉多态中存在的这个问题很新颖&#xff0c;故分享之&#xff1b; 【1】继承与is-a法则 1.1&#xff09;有一个用来判断是否应该设计为继承关系的规则&#xff1a; 这就是 is-a 规则&#xff0c; 它…

MacOS命令终端(CMD)的快捷键/终端快捷键

文章目录常用删除清屏复制粘贴交互/撤销移动光标查找历史命令使用命令查看历史命令标签页控制命令滚屏常用 快捷键说明Control A跳到本行的行首Control E跳到本行的行尾Control U删除光标前面&#xff08;左侧&#xff09;的所有文字&#xff08;还有剪切功能&#xff09;&…

apache kafka_使用Apache Kafka,Kubernetes和Envoy,Istio,Linkerd的服务网格和云原生微服务...

apache kafka微服务架构不是免费的午餐 &#xff01; 微服务需要解耦&#xff0c;灵活&#xff0c;操作透明&#xff0c;数据感知和弹性。 过去几年的大多数材料仅讨论具有紧密耦合且不可扩展的技术&#xff08;如REST / HTTP&#xff09;的点对点体系结构。 这篇博客文章介绍了…

c++ 箭头符号怎么打_老司机怎么测量三极管管型、管脚和性能?三极管测量此中有深意...

众所周知&#xff0c;三极管具有基极、集电极、发射极三极&#xff0c;另外还有NPN型还有PNP型&#xff0c;那么如何用最快的方法进行三极管测量来确认三极管的管脚和管型。另外&#xff0c;三极管的工作状态是否可以通过三极管测量进行判断&#xff1f;接下来本网整理了老司机…

java强制类型转换

【0】README 0.1&#xff09;本文转自 core java volume 1 &#xff0c;在强制类型转换部分&#xff0c;它提到了 使用 instanceof 以保证 类型成功转换&#xff08;而不是抛出异常&#xff09;&#xff0c;很有看点&#xff1b; 【1】强制类型转换的相关知识点&#xff1a; …

MacBook快捷键

文章目录一、选择文本二、移动光标三、打开特定的目录四、录屏/截屏五、选择输入法六、视窗七、窗口缩放八、检索/搜索九、目录路径十、页面滚动十一、删除/清空回收站十二、显示隐藏文件十三、程序坞十四、关机十五、清理缓存十六、窗口最小化十七、分屏十八、Finder/访达窗口…

php cdi_通过MicroProfile上下文传播增强了CDI上下文和隔板

php cdi当将CDI与异步执行方法&#xff08;例如ManagedExecutorService &#xff0c;传统上不可能访问在原始线程中处于活动状态的所有CDI范围。 MicroProfile Context Propagation可以定义线程执行上下文并将其传递到完成阶段&#xff0c;尽管我们的代码是异步执行的&#xff…

Final Cut Pro X 快捷键

文章目录一、片段编辑二、导出/导入媒体三、选取/选择片段四、修剪&#xff08;一&#xff09;修剪模式的三种修剪效果五、其它编辑快捷键六、光标功能状态切换七、移动播放头八、播放九、插入媒体素材到时间线十、更改片段在时间线的外观十一、为片段添加/删除效果十二、为片段…

求三个数的最大最小值

【0】README 0.1&#xff09; google 搜索出来的答案&#xff0c;真的很让我伤心&#xff0c; 全是大粪啊&#xff0c; 你们进行了多少次的比较&#xff0c; 应该是6次吧&#xff0c;我也是醉完了&#xff0c; 写个非大粪的version &#xff08;我这里的比较只有两次&#xff…

斐讯k1潘多拉专版固件_斐讯K1刷专版潘多拉固件以及教程(使用感受)

本帖最后由 Super131 于 2016-3-5 10:09 编辑QQ图片20160225010211.png (24.22 KB, 下载次数: 2)2016-2-25 01:02 上传K1的专版潘多固件最有看点一个地方我觉得是外观&#xff0c;比起之前显得让人看着舒服多了QQ图片20160225010400.png (41.37 KB, 下载次数: 0)2016-2-25 01:0…

魔术方法 类 序列化_Java序列化魔术方法及其示例使用

魔术方法 类 序列化在上一篇文章中&#xff0c; 您需要了解有关Java序列化的所有知识 &#xff0c;我们讨论了如何通过实现Java序列化来启用类的可序列化性。 Serializable接口。 如果我们的类未实现Serializable接口&#xff0c;或者该类具有对非Serializable类的引用&#x…

算法证明_CFR+算法证明过程

在介绍CFR算法之前&#xff0c;我们首先介绍一下基础概念。在CFR算法中&#xff0c;counterfactual utility被定义为以下形式&#xff1a;然后在regret的基础上&#xff0c;CFR算法定义了一个regretlike value&#xff0c;注意在这里CFR算法的regret为一个累加值&#xff0c;而…

java继承中的 equals + hashCode+toString

【0】README 0.1&#xff09;本文转自 core java volume 1&#xff0c; 旨在理清 equals hashCode方法&#xff1b; 0.2&#xff09; 特别说明&#xff1a; 在java中&#xff0c; 只有基本类型不是对象&#xff0c; 例如&#xff0c;数值&#xff0c; 字符和布尔类型的值都不…

纹理和基元_自定义基元和DTO的(反)序列化和验证

纹理和基元最近&#xff0c;我们为您提供了新的HTTP框架HttpMate。 在介绍性文章中 &#xff0c;我们将请求和响应映射到域对象称为“最复杂的技术细节”&#xff0c;以及如何通过另一个伴侣MapMate帮助我们。 实际上&#xff0c;当将请求属性映射到您的域对象时&#xff0c;M…

vim 常用命令

文章目录普通命令模式下技巧汇总切换到插入模式切换到可视模式切换至底行命令模式复制内容复制命令的记忆技巧粘贴/恢复修改/改写删除/剪切字符大小写切换选择文本游标移动剪切文本/移动文本滚屏/翻页撤回查看文档状态查找/搜索字符串查看历史命令查看历史搜索记录多窗口操作保…

常见花材的固定的方法有哪些_旋流器常见的故障及处理方法有哪些?

旋流器除了用在磨矿循环中的分级作业外&#xff0c;还可以用于脱泥、脱水以及脱除浮选药剂等。此外&#xff0c;还可以用做重悬浮液选矿&#xff0c;其分选粒度可达0.1毫米左右。旋流器有许多优点&#xff0c;构造简单&#xff0c;没有运动部件&#xff0c;单位容积的处理能力大…