《算法导论》第11章 散列表 练习题

11.1 直接寻址表

练习

11.1-1 考虑由一个长度为m的直接寻址表T表示的动态集合S。给出一个查找S的最大元素的算法过程。所给的过程在最坏情况下的运行时间是什么?

如果不排序的话,最坏时间复杂度是O(m),用快排降序排列,最坏情况是O(lgm)。

11.1-2 位向量(bit vector)是一种仅包含0和1的数组。长度为m的位向量所占空间要比包含m个指针的数组少得多。请说明如何用一个位向量来表示一个包含不同元素(无卫星数据) 的动态集合。字典操作的运行时间应是O(1)。

(“Satellite data”指的是与主数据相关的附加信息或元数据。在数据结构中,卫星数据通常是指存储在主要数据之外的额外信息。这些数据可能用于提供上下文、描述或补充主要数据,而在某些情况下,可以仅关注主要数据本身,不需要这些附加信息。)

非常简单,用连续数组就行了。插入操作设置为1,删除操作设置为0,查找返回是否等于1。

11.1-3 说明如何实现一个直接寻址表,使各元素的关键字不必都不相同,且各元素可以有卫星数据。所有三种字典操作(INSERT,DELETE和 SEARCH)的时间应为O(1)。(不要忘记 DELETE指向要删除的对象的指针变量,而不是关键字。)

如果不考虑卫星数据,那么直接覆盖就行了,三种操作时间复杂度都是O(1)。如果要保留关键字相同但是卫星数据不同的元素,那么使用链表法,但是复杂度变大:

  • INSERT: 时间复杂度为 O(1)O(1),因为在链表头插入节点。
  • SEARCH: 时间复杂度为 O(n)O(n),其中 nn 是链表中节点的数量,需遍历整个链表以获取所有数据。
  • DELETE: 时间复杂度为 O(n)O(n),最坏情况下需要遍历链表寻找要删除的节点。

*11.1-4 我们希望通过利用在一个非常大的数组上直接寻址的方式来实现字典。开始时,该数组中可能包含废料,但要对整个数组进行初始化是不实际的,因为该组的规模太大。请给出在大数组上实现直接寻址字典的方案。每个存储的对象占用 O(1)空间;操作SEARCH,INSERT和 DELETE的时间为 O(1);对数据结构初始化的时间为 O(1)。(提示:可以利用另外一个栈,其大小等于实际存储在字典中的关键字数目,以帮助确定大型数组中某个给定的项是否是有效的。)

假设一个项key,查找进行的操作就是,首先进行 value = hash(key),此value就是此key在Array的位置,根据此索引得到一个值index = Array[value],再根据此index在St中寻找,如果栈中有此索引,那么这个值就存在,且St(index) == key,总的来说就是 St[Array[hash[key]]] == key;

The downside of direct addressing is obvious: if the universe U is large, storing
a table T of size j U j may be impractical, or even impossible, given the memory
available on a typical computer. Furthermore, the set K of keys actually stored
may be so small relative to U that most of the space allocated for T would be
wasted.
When the set K of keys stored in a dictionary is much smaller than the uni
verse U of all possible keys, a hash table requires much less storage than a direct
address table. Specifically, we can reduce the storage requirement to ‚. j K j / while
we maintain the benefit that searching for an element in the hash table still requires
only O.1/ time. The catch is that this bound is for the average-case time , whereas
for direct addressing it holds for the worst-case time .
With direct addressing, an element with key k is stored in slot k . With hashing,
this element is stored in slot h.k/ ; that is, we use a hash function h to compute the
slot from the key k . Here, h maps the universe U of keys into the slots of a hash
table T [0. . m-1] :
h : U -> {0, 1, ... , m-1},
where the size m of the hash table is typically much less than j U j . We say that an
element with key k hashes to slot h.k/ ; we also say that h.k/ is the hash value of
key k . Figure 11.2 illustrates the basic idea. The hash function reduces the range
of array indices and hence the size of the array. Instead of a size of j U j , the array
can have size m .

这其实是模拟散列表了,不是单纯的直接寻址。

另一种做法:

增加两个动态数组,S和S',类似于栈,初始化时都为空,当某个关键字变成有效时,压入数组,其最大大小为实际存储在字典中的关键字数目。记直接寻址表为T,当某个关键字k变有效时,T[k]里存储S和S'的索引i,即T[K]=i;S[i]里存储那个有效的关键字k,即S[i]=k;S'[i]里存储指向卫星数据的指针。

11.2 散列表

练习题

11.2-1 假设用一个散列函数h,将n个不同的关键字散列到一个长度为m 的数组T中。假定采用的是简单一致散列法,那么期望的碰撞数是多少?更准确地,集合{{k,l}:k≠l,且h(k)=h(D)}的期望的基是多少?

在简单均匀散列的情况下,假设我们有n个不同的关键字,将它们散列到一个长度为m的数组T中。每个关键字被散列到m个槽中的任意一个槽上是等概率的。

令C表示冲突的数量,即有两个不同的关键字散列到相同的槽中。我们可以使用指示器随机变量来表示冲突情况。定义指示器变量I_{kl},如果关键字k和关键字l发生冲突(即h(k) = h(l)),则I_{kl} = 1,否则为0。

我们可以写出冲突数C的表达式:

C=求和I_kl (1<=k<l<=n)

期望的冲突数E[C] 是指冲突数C的期望值。由于期望是线性的,我们可以将期望移到求和符号中:

E[C]=E[求和I_kl (1<=k<l<=n)]

然后,我们可以使用简单均匀散列的假设,即每对关键字发生冲突的概率是相同的:

E[C]=求和E[I_kl] (1<=k<l<=n)

因为每对关键字发生冲突的概率相同,所以我们只需要计算一对关键字的冲突概率,并乘以所有可能的一对关键字的数量。有n*(n-1)/2 种可能的一对关键字,所以:

E[C] = n*(n-1)/2 * E[I_12]

现在,考虑任意一对关键字k和l,它们发生冲突的概率是散列函数将它们映射到相同槽的概率。由于采用简单均匀散列,槽的选择是均匀的,所以任意一对关键字发生冲突的概率是 1/m。因此:

E[C]=n*(n-1)/2 * (1/m)

这就是期望的冲突数。

答案出处

11.2-2 对于一个利用链接法解决碰撞的散列表,说明将关键字5、28、19、15、20、33、12、17、10插入到该表中的过程。设该表中有9个槽位,并设散列函数为 h(k)=kmod9。
11.2-3 Marley 教授做了这样一个假设,即如果将链接模式改动一下,使得每个链表都能保持已排序顺序,散列的性能就可以有很大的提高。Marley 教授的改动对成功查找、不成功查找、插人和删除操作的运行时间有什么影响?
11.2-4 说明在散列表内部,如何通过将所有未占用的槽位链接成一个自由链表,来分配和去配元素的存储空间。假定一个槽位可以存储一个标志、一个元素加上一个或两个指针。所有的字典和自由链表操作应具有O(1)的期望运行时间。该自由链表需要是是双链表吗? 或者,是不是单链表就足够了?
11.2-5 证明:如果|U{>nm,有一个U的大小为n的子集,它包含了均散列到同一槽位中的关键字,这样对于带链接的散列表,最坏情况下的查找时间为 θ(n)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值