《信息学奥赛课课通(C++)》第7单元 基本数据结构.ppt

《信息学奥赛课课通(C++)》第7单元 基本数据结构.ppt

  1. 1、本文档共104页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
1. 哈希表的基本概念 哈希表的基本原理是使用一个下标范围比较大的数组 A 来存储元素,设计一个函数 h,对于要存储的线性表的每个元素 node,取一个关键字 key,算出一个函数值 h(key),把 h(key) 作为数组下标,用 A[h(key)] 这个数组单元来存储 node。也可以简单的理解为,按照关键字为每一个元素“分类”,然后将这个元素存储在相应“类”所对应的地方(这一过程称为“直接定址”)。 1. 哈希表的基本概念 但是,不能够保证每个元素的关键字与函数值是一一对应的,因此极有可能出现对于不同的元素,却计算出了相同的函数值,这样就产生了“冲突”,换句话说,就是把不同的元素分在了相同的“类”之中了。假设一个结点的关键字值为key,把它存入哈希表的过程是根据确定的函数h计算出h(key)的值,如果以该值为地址的存储空间还没有被占用,那么就把结点存入该单元;如果此值所指单元里已存储了别的结点(即发生了冲突),那么就再用另一个函数I进行映射,计算出I(h(key)),再看用这个值作为地址的单元是否已被占用了,若已被占用,则再用I映射,…直至找到一个空位置将结点存入为止。当然,这只是解决“冲突”问题的一种简单方法,如何避免、减少和处理“冲突”是使用哈希表的一个难题。 1. 哈希表的基本概念 在哈希表中查找元素的过程与建立哈希表的过程相似,首先计算 h(key) 的值,以该值为地址到基本区域中去查找。如果该地址对应的空间未被占用,则说明查找失败;否则用该结点的关键字值与要找的 key 比较,如果相等则查找成功;否则要继续用函数I计算 I (h(key)) 的,……如此重复,或者求出的某地址空间未被占用(查找失败)或者比较相等(查找成功)为止。 例1、用哈希表存储以下线性表(18,75,60,43,54,90,46)。 【问题分析】 假设选取的哈希函数为 h(K) = K mod m,K 为元素的关键字,m 为哈希表的长度,用余数作为存储该元素的哈希地址。K 和 m 均为正整数,并且 m 要大于或等于线性表的长度 n。此例n = 7,故取 m = 13 就已经足够,得到的每个元素的哈希地址为: h(18)=18 mod 13=5 h(75)=75 mod 13 =10 h(60)=60 mod 13=8 h(43)=43 mod 13=4 h(54)=54 mod 13=2 h(90)=90 mod 13=12 h(46)=46 mod 13=7 根据哈希地址,依次把元素存储到哈希表 H(0 ~ m-1)中的效果如下: 这是一个比较理想的情况,假如要再往表中插入第 8 个元素 30,h(30) = 30 mod 13 = 4,会发现 H[4] 已经存放了 43,此时就发生了冲突,那么就可以从 H[4] 往后按顺序找一个空位置存放 30,即可以把它插入到 H[6] 中。 2. 哈希表的应用举例 例2、分身数对 【问题描述】 给出 n 个不同的正整数 a[1] ~ a[n],它们的值在 1~1000000 之间。再给定一个整数 x,编程计算这样的数对个数(a[i],a[j]),1≤ij≤n 并且 a[i]+a[j]=x。 【输入格式】 第 1 行 1 个正整数 n,1≤n≤100000。 第 2 行 n 个正整数,表示元素 a[1] ~ a[n],每两个数之间用一个空格分隔。 第 3 行 1 个正整数 x,1≤x≤2000000。 【输出格式】 一行一个整数,表示这样的数对个数。 【输入样例】 9 5 12 7 10 9 1 2 3 11 13 【输出样例】 3 【样例说明】 不同的和为 13 的数对是(12,1),(10,3)和(2,11),共 3 对。 【问题分析】 如果使用双重循环来查找,本题是要超时的。用哈希表来处理,定义 a[x] 代表 x 这个数在数列中是否存在,1 代表存在,0 代表不存在,那么只需要扫描 1 ~ x/2,若数字存在,那么只需要查看 x 减去这个数的结果在数列里是否存在,若存在就增加一对数对。 具体程序参考教材274页。 例3、明明的随机数 【问题描述】 明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了 N 个 1~1000 之间的随机整数,N≤100,对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请协助明明完成“去重”与“排序”的工作。 【输入格式】 第 1 行为 1 个正整数,表示所生成的随机数的个数 N。 第 2 行有 N 个用一个空格隔开的正整数,为所产生的随机数。 【输出格式】 输出两行。 第 1 行为 1 个正整数 M,表示不相同的随机

文档评论(0)

一壶清茶 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档