算法导论 11.1-4 大数组的直接寻址表

一、题目

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


二、思考

由于数组太大不能初始化,因此本题主要要解决的问题是在不能初始化数组有情况下,怎么判断数组中的值是不是有效的key。

用一个栈来存储实际插入的数据,插入时栈向上扩展一个空间,删除时,用栈顶元素补充被删除元素的位置,栈向下回收一个空间,方法类似于P127-11.3-4.

这个非常大的数组中不直接存放数据,而是存放数据在Stack中的位置。

对于一个元素p,如果H[p] < 栈中总元素的个数 && p = Stack[H[p]],就是存入,否则就是不存在


三、代码

#include <iostream>
#include <string>
using namespace std;

//查找,若存在则返回在栈中的位置
int Search(int *Hash, int *Stack, int value)
{
	int p = Hash[value];
	//存在的条件:1.H[p]表示的是栈中的位置2.这个位置在Stack的范围中3.这个位置存储是这个值
	if(p > 0 && p <= Stack[0] && Stack[p] == value)
		return p;
	return 0;
}
//插入
int Insert(int *Hash, int *Stack, int value)
{
	int ret;
	//验证这个值是否存在
	if(ret = Search(Hash, Stack, value))
	{
		cout<<"error:already in "<<ret<<endl;
		return 0;
	}
	//扩充栈的大小
	Stack[0]++;
	//把待插入的值存在新扩充的空间
	Stack[Stack[0]] = value;
	//把值在栈中的位置记录到散列表中
	Hash[value] = Stack[0];
	return Stack[0];
}
//删除一个元素
int Delete(int *Hash, int *Stack, int value)
{
	//验证这个值是否存在
	int ret = Search(Hash, Stack, value);
	if(ret == 0)
	{
		cout<<"error:not fount"<<endl;
		return 0;
	}
	//获取值在栈中的位置
	int v = Stack[Stack[0]];
	//用栈顶元素填充这个被删去的空间,更新散列表
	Hash[v] = ret;
	Stack[ret] = v;
	//栈的大小-1
	Stack[0]--;
	return ret;
}
//输出栈中存储的值
void Print(int *Stack)
{
	int i;
	for(i = 1; i <= Stack[0]; i++)
		cout<<Stack[i]<<' ';
	cout<<endl;
}
int main()
{
	string str;
	int x;
	int Hash[10000];
	int Stack[100] = {0};
	while(1)
	{
		cin>>str;
		if(str == "I")
		{
			x = rand() % 100;
			cout<<x<<endl;
			Insert(Hash, Stack, x);
		}
		else if(str == "D")
		{
			cin>>x;
			Delete(Hash, Stack, x);
		}
		else if(str == "P")
		{
			Print(Stack);
		}
	}
	return 0;
}


 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值