一、题目
我们希望我们希望通过利用在一个非常大的数组上直接寻址的方式来实现字典。开始时,该数组中可能包含废料,但要对整个数组进行初始化是不实际的,因为该数组的规模太大。请给出在大数组上实现直接寻址字典方案。每个存储的对象占用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;
}