【原创】算法导论11章带星第4题试解

题目:

我们希望在一个【非常大】的数组上,通过利用直接寻址的方式来实现一个字典。开始时,该数组中可能包含一些无用信息,但要对整个数组进行初始化是不太实际的,因为该数组的规模太大。请给出在大数组上实现直接寻址字典的方案。每个存储对象占用O(1)空间;SEARCH、INSERT和DELETE操作的时间均为O(1);并且对数据结构初始化的时间为O(1)。

(提示:可以利用一个附加数组,处理方式类似于栈,其大小等于实际存储在字典中的关键字数目,以帮助确定大数组中某个给定的项是否有效)

解答:

这个提示非常微妙啊。神马叫“类似于栈”?但参透这个提示真意的话,解决问题也就不远了。

【类似于栈】,可以理解为以栈的方式来加入数据结构,但【可以随机访问】整个栈。

不妨设大数组为array,附加数组为mystack,栈顶指针为top,初始化为 -1。

我们每插入一个数据item,就把该数据通过mystack[++top]的方式添加到栈中,同时,将array[item]的值设为top。

查找的时候,先通过array[item]找到数据在栈中的位置pos,如果pos比栈的容量大,那肯定查找失败;如果pos小于栈的容量且mystack[pos] == item,那么查找成功。剩下的情况都算查找失败。表示为C代码:

if (array[item] <= top && mystack[array[item]] == item)

  return 1;

else

  return 0;

删除的时候呢?怎么保持提示中所说的“其大小等于实际存储在字典中的关键字数目”?

这里有一个比较hack的方法,分两种情况。

0、栈顶元素要被删除:直接top --

1、栈内元素要被删除:设被删除元素栈内序号为k,则swap(&mystack[k],&mystack[top])之后,【更新array[mystack[top]]的值为k】

为什么呢?

因为array数组存储的是数据在栈中的位置,mystack[top]并没有被删除,但是存储位置改变了,因此,必须修改array[mystack[top]]的值为原栈顶数据在栈中的新位置。

总结:

大概是这么个逻辑:

我要找数据tmp:

(获得了tmp在栈中的位置)

tmp --------> array --------> mystack

(栈中特定位置上是tmp吗?)

时间: 2024-08-05 06:01:29

【原创】算法导论11章带星第4题试解的相关文章

算法导论 第二章

2014-12-02 20:21:40 http://www.cnblogs.com/sungoshawk/p/3617652.html 上面链接指向算法导论第二章的预习博客,很值得一看,很详细. 插入算法: 1 #include <iostream> 2 3 using namespace std; 4 void insert_sort(int *datas, int length); 5 int main() 6 { 7 int a[10]={1,2,4,35,6,1,4,7,9,7};

算法导论 第一章

算法导论 第一章,为了让自己基本功更加的扎实,从今天起开始学习算法导论. 我以一位学长的博客为学习的参考资料,开始我的学习吧! 附上一句话: Having a solid base of algorithm knowledge and technique is one characteristic that separates the truly skilled programmers from the novices. 是否具有扎实的算法知识和技术基础,是区分真正熟练的程序员与新手的一项重要特

算法导论第九章中位数和顺序统计量(选择问题)

本章如果要归结成一个问题的话,可以归结为选择问题,比如要从一堆数中选择最大的数,或最小的数,或第几小/大的数等, 这样的问题看似很简单,似乎没有什么可研究的必要,因为我们已经知道了排序算法,运用排序+索引的方式不就轻松搞定了?但细想,排序所带来的时间复杂度是不是让这个问题无形之中变得糟糕.那算法研究不就是要尽可能避免一个问题高复杂度地解决,让那些不敢肯定有无最优解的问题变得不再怀疑,这也是算法研究者所追求的一种极致哲学.既然排序让这个问题解决的性能无法确定,那我们就抛开排序,独立研究问题本身,看

算法导论第二章C++实现归并算法排序

归并算法排序的思想算法导论中讲的还算比较清楚. #include<iostream> using namespace std; void guibing(int *_array,int p,int q,int r); void merge_sort(int *_array,int p,int r); int main() { int a[8]={2,4,5,7,1,2,3,6}; int j1=0; int j2=7; merge_sort(a,j1,j2); int i=0; for(;i&

【原创】《算法导论》链表一章带星习题试解——附C语言实现

原题: 双向链表中,需要三个基本数据,一个携带具体数据,一个携带指向上一环节的prev指针,一个携带指向下一环节的next指针.请改写双向链表,仅用一个指针np实现双向链表的功能.定义np为next XOR prev,请根据表头提供的信息,为双向链表编写插入函数.删除函数和查找函数,并在O(1)时间内实现链表的翻转. 分析: 问题的关键,在于怎样利用prev指针和next指针的异或结果,来获得上一节点或下一节点的地址值.也就是说,如何利用异或来算出具体的prev及next值.我们注意到两点: 1

算法导论2-9章补充几道题

本篇博文意在对前几章中遗漏的,本人觉得有意思的习题当独拿出来练练手. 1.习题2-4,求逆序对,时间复杂度要求Θ(nlgn) 定义:对于一个有n个不同的数组A, 当i<j时,存在A[i]>A[j],则称对偶(i, j)为A的一个逆序对. 譬如:<2,3,8,6,1>有5个逆序对. 解题思路:归并排序的思想:逆序对的数量=左区间的逆序对+右区间的逆序对+合并的逆序对 代码如下: 1 #include <iostream> 2 #include <vector>

算法导论23章思考题(转载)

23-1次优最小生成树 a. 最小生成树唯一性证明: 已知当前构造的边集A是最小生成树的子集.令无向图G的一个切割是,显然该切割是尊重A的.已知跨越该切割的轻量级边对于A是安全的,又因为该无向图G的每条边的权值都不相同,所以对于当前A而言,安全边有且只有一条,即对于每个状态下的A,构造最小生成树的方式是唯一的.所以最小生成树是唯一的. 次优最小生成树不唯一性证明: 如上图:{(C, D), (A, D), (A, B)} 和 {(C, D), (A, C), (B, D)} 是两个次优最小生成树

算法导论 第二章作业

//作业2. 1-2 template<class T> void insert(T* A, int  n) { for (int j = 1; j < n; ++j) { T key = A[j]; int i = j - 1; while (i >= 0 && key > A[i]) { A[i + 1] = A[i]; --i; } A[i + 1] = key; } } //2. 1-3 template<class T> void fin

【算法导论第二章】算法基础

2.1插入排序 扑克牌这个栗子不错.以后得多用扑克牌来形象化思考排序问题. 根据伪代码用java实现插入排序 package com.panjn.java; /** * Created by panjianning on 2016/7/10. */ public class InsertionSort { public static void main(String[] args) { int[] array = new int[]{1, 3, 5, 7, 9, 2, 4, 6, 8, 10};