11-散列4 Hashing - Hard Version(30 分)
题目地址:11-散列4 Hashing - Hard Version(30 分)
题目描述:
Given a hash table of size N N N, we can define a hash function . 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.
解题方法:
最后还是参考了别人的写法,这道题主要是通过拓扑排序和优先级队列(实际上也就是最小堆)来解决。
可以通过计算冲突数来决定入度。如果冲突数为3,那么也就是说在当前位置的元素插入之前,该位置前面的3个位置必须先有元素才行,这样也就引申出当前元素的入度为3。每当前面的元素输出一个,就把他从优先级队列中去除同时把当前元素的入度-1,当有新的元素入度为0时,在插入优先队列。
易错点
题目中说空位用负数表示,且不唯一。所以在判断空位的条件是>=0。之前没注意,看了好久都没找出错误。
程序:
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <queue>
using namespace std;
int Arr[1001];
int ConflictTimes(int i, int key, int tablesize)
{ /* 计算每一个结点的冲突次数 */
return (i - key%tablesize + tablesize) % tablesize;
}
int Hash(int key, int tablesize)
{ /* 计算初始映射位置 */
return key % tablesize;
}
struct cmp
{ /* 比较函数 小顶堆 */
bool operator() (int i, int j)
{
return Arr[i] > Arr[j];
}
};
int main(int argc, char const *argv[])
{
int N, x, flag = 0;
scanf("%d", &N);
int Indegree[N];
vector <vector<int> > v(N);
priority_queue<int, vector<int>, cmp> q;
for (int i = 0; i < N; i++)
{ /* 计算每一个值的冲突次数也即入度 */
scanf("%d", &x);
Arr[i] = x;
if (x >= 0) /* 跳过空位 */
{
int pos = Hash(x, N);
Indegree[i] = ConflictTimes(i, x, N);
if (Indegree[i]) /* 如果入度不是0 */
for (int j = 0; j <= Indegree[i]; j++)
v[Hash(pos+j, N)].push_back(i);
else /* 如果入度为0则直接放入优先级队列 */
q.push(i);
}
}
while (!q.empty())
{ /* 如果队列不空,每次取队头元素,并将以队头元素为前驱的元素入度-1 */
int pos = q.top();
q.pop();
if (flag == 1)
printf(" ");
printf("%d", Arr[pos]);
flag = 1;
for (int k = 0; k < v[pos].size(); k++)
if (--Indegree[v[pos][k]] == 0)
q.push(v[pos][k]);
}
return 0;
}
如果对您有帮助,帮忙点个小拇指呗~
本文介绍了一种利用拓扑排序和优先级队列解决散列表重构问题的方法。针对已知散列表状态,逆向推导出原始输入序列,重点讲解了如何通过计算冲突次数确定元素的入度。
564





