不用拓补排序 不用求偏移量——11-散列4 Hashing - Hard Version

11-散列4 Hashing - Hard Version——不用拓补排序 不用求偏移量

题目地址:11-散列4 Hashing - Hard Version(30 分)

题目描述
Given a hash table of size N, we can define a hash function H(x)=x%N. Suppose that the linear probing is used to solve collisions, we can easily obtain the status of the hash table with a given sequence of input numbers.

However, now you are asked to solve the reversed problem: reconstruct the input sequence from the given status of the hash table. Whenever there are multiple choices, the smallest number is always taken.

输入格式
Each input file contains one test case. For each test case, the first line contains a positive integer N (≤1000), which is the size of the hash table. The next line contains N integers, separated by a space. A negative integer represents an empty cell in the hash table. It is guaranteed that all the non-negative integers are distinct in the table.

输出格式
For each test case, print a line that contains the input sequence, with the numbers separated by a space. Notice that there must be no extra space at the end of each line.

思路
事实上,我们可以将问题局限在hash表本身,不需要考虑“入度”、堆等问题。就像除一个数相当于乘它的倒数一样,既然是一个hashing的逆过程,我们自然可以模拟hashing的过程来实现它。
更重要的是,在有多种选择时,我们总是选择较小的数,那么这也为我们解决问题提供了便利。
具体的操作是,将输入进来的数排序,然后从小到大一个一个进行尝试。如果现在加进去是它现在的位置,那么就输出它,并再到回到开头,再次从小到大尝试。(递归)

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int outtimes=0, psn = 0,flag = 1;//将来可能会在递归中用到的计数器
void print(vector<struct node> &v, vector<int> &h, int n, vector<int> v1);
struct node {//对于每个数,需要知道它的大小和状态(-1不能放入或尚未尝试到,1是已输出,并且找到了位置)
	int data;
	int status;
};
int hashing(int x,int p)//找位置需要
{
	return x%p;
}
bool cmp(const struct node &n1, const struct node &n2)
{
	return n1.data < n2.data;
}
int find(const vector<int> &vv1, const int &x)//对于已建好的和未见好的hash表来说,可用同一个函数来寻找它们的位置
{
	int cnum=1,pos = hashing(x, vv1.size());
	int pos1=pos;
	while (vv1[pos] >= 0&&vv1[pos]!=x)
	{
		pos = (pos1 + cnum) % vv1.size();//不是一般的加减加减的情况
		cnum++;
	}
	return pos;
}
int main(void)
{
	vector<int> v1,h;
	vector<struct node> v2;
	int n, pos, x,pos1;
	struct node y;
	cin >> n;
	for (int i = 0; i < n; i++)//有些复杂的输入(构造三个容器)
	{
		cin >> x;
		if (x >= 0)//准备在统计将来输出次数(比较low的避免末尾空格的方法)
			psn++;
		v1.push_back(x);
		y.data = x;
		y.status = -1;
		v2.push_back(y);
		h.push_back(-1);
	}
	sort(v2.begin(), v2.end(), cmp);//将v2中的数据排序好
	while(1)
	{
		print(v2, h, n, v1);
		if (flag == 1)//当没有状态为-1的数时,说明输出完成
			break;
		flag = 1;
	}
	return 0;
}
void print(vector<struct node> &v, vector<int> &h, int n,vector<int> v1)
{
	int pos1,pos;//两个位置,pos在v2中,pos1记录在v1中的位置
	for (pos = 0; pos != n; pos++)
	{
		if (v[pos].data >= 0 && v[pos].status == -1)//不是空的,需要尝试
		{
			pos1 = find(h, v[pos].data);
			flag = -1;//做到这一步说明还有需要输出的,改为-1
			if (pos1 == find(v1, v[pos].data))//关键:两者中位置相同
			{
				h[pos1] = v[pos].data;//同时要更新h中的状态
				v[pos].status = 1;
				cout << v[pos].data;
				if (outtimes < psn - 1)//low的避免空格的方法
					cout << ' ';
				outtimes++;
				print(v, h, pos,v1);//返回找之前是不是有数也可以被输出了
			}
			else
				;//不需要更新-1
		}
		else
			v[pos].status = 1;//即使是空的,也需要更新状态
	}
}

(其实在每一遍遍历入度时,就是在尝试将其放入新建hash表)
小白第一次发博客,可能有错误,欢迎大佬们指出~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值