11-散列4 Hashing - Hard Version

Given a hash table of size 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.

Input Specification:

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.

Output Specification:

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.

Sample Input:

11
33 1 13 12 34 38 27 22 32 -1 21

Sample Output:

1 13 12 21 33 34 38 27 22 32

题意解析:

  1. 对于每一个哈希表中的元素,根据哈希函数(这里是除留取余法,若是其他方法同理)进行放置,如若产生冲突,采用线性探测法解决;
  2. 那么遍历整个哈希表,通过哈希函数可以计算出第一次冲突的位置Pos,此时该元素的位置为i,可知从Pos到i-1位置的元素一定比该元素先插入哈希表,有没有想到拓扑序;                                                                                                                        (注意:题目要求优先将数值较小的元素插入,因此冲突次数较高的小元素可能比冲突次数为0的大元素还要早插入)
  3. 对于这种次序优先的问题联想到拓扑排序,根据散列表建立有向图(这里采用邻接表),遍历散列表,对位于i位置且有冲突的元素,向前扫描直至到Pos(哈希函数计算),冲突次数即为该元素入度值,每经过位置j(j从i到Pos扫描),构建一条     j->i的有向边,表示i位置的元素必须在j位置元素之后插入哈希表;                                                                                             (注意是用元素在哈希表的位置表示顶点建图,将元素值存储在图中的邻接表的Data值中)
  4. 该题拓扑排序注意:不同于之前计算机选课排序问题里将入度值为0的顶点全部入队,这里只能将最小的入度值为0的顶点入队,出队后进行标识(这里我将其入度更新为INFINITY),继而更新该顶点指向的顶点的入度值-1(表示该元素已插入哈希表,与它产生一次冲突的元素也可以插入了),直至所有顶点的入度值全为INFINITY(哈希表对应位置为空的入度值提前更新为INFINITY,不进行拓扑排序),这里用一个数组来存储出队的顶点。
#include
#include
#define Vertex int
#define DataType int
#define MaxSize 1000
#define Position int
#define INFINITY 65535

typedef struct VNode *PtrToVNode;
struct VNode{
	Vertex V;
	PtrToVNode Next;
};

typedef struct AdjVNode{
	PtrToVNode FirstEdge;
	DataType Data;
}*AdjList;

typedef struct GNode *LGraph;
struct GNode{
	int GraphSize;
	AdjList G;
};

typedef struct QNode *Queue;
struct QNode{
	int QSize;
	int front;
	int rear;
	Vertex *Q;
};

LGraph CreateGraph(int N);
void InsertEdge(LGraph G,Vertex V1,Vertex V2);
void TopSort(LGraph G,int B[]);
Vertex FindMinV(LGraph G);
Queue CreateQ(int N);
void AddQ(Queue Q,Vertex V);
Vertex DeleteQ(Queue Q);
int IsEmptyQ(Queue Q);

int InDegree[MaxSize];

int main()
{
	int i,N,A[MaxSize];
	LGraph G;
	Position Pos,j;
    /*图的建立*/ 
	scanf("%d",&N);
	G=CreateGraph(N);
	for(i=0;iG[i].Data=A[i];
	}
		
	for(i=0;iGraphSize=N;
	G->G = (AdjList)malloc(N*sizeof(struct AdjVNode));
	for(V=0;VG[V].FirstEdge=NULL;
	return G;
}

void InsertEdge(LGraph G,Vertex V1,Vertex V2)
{
	PtrToVNode NewNode=(PtrToVNode)malloc(sizeof(struct VNode));
	NewNode->V=V2;
	NewNode->Next=G->G[V1].FirstEdge;
	G->G[V1].FirstEdge=NewNode;
}

void TopSort(LGraph G,int B[])
{
	Vertex V;
	int i=0;
	Queue Q;
	PtrToVNode P=(PtrToVNode)malloc(sizeof(struct VNode));
	
	Q=CreateQ(G->GraphSize);
	V=FindMinV(G);//寻找入度值为0的最小顶点
	AddQ(Q,V);
	while(!IsEmptyQ(Q))
	{
		V=DeleteQ(Q);
		InDegree[V]=INFINITY;//标识为已寻找
		B[i++]=V;
		for(P=G->G[V].FirstEdge;P;P=P->Next)//更新邻接顶点的入度值
			InDegree[P->V ]--;
		V=FindMinV(G);//更新入度值之后再次寻找
		if(V==-1)//寻找失败
			break;
		else
			AddQ(Q,V);
	}
    B[i]=-1;//结束标志
}

Vertex FindMinV(LGraph G)
{
	Vertex V,MinV=-1;
	for(V=0;VGraphSize ;V++)
	{
		if(InDegree[V]==0)//入度为零
		{
			if(MinV==-1)//初始化
				MinV=V;
			else if(MinV!=-1 && G->G[V].Data G[MinV].Data )//更新元素值更小的顶点
			{
				MinV=V;
			}
		}
	}
	return MinV;
}

Queue CreateQ(int N)
{
	Queue Q=(Queue)malloc(sizeof(struct QNode));
	Q->QSize=N;
	Q->Q=(Vertex *)malloc(N*sizeof(Vertex));
	Q->front=Q->rear=-1;
	return Q;
}

void AddQ(Queue Q,Vertex V)
{
	Q->Q[(++ Q->rear)% Q->QSize ]=V;
}

Vertex DeleteQ(Queue Q)
{
	return Q->Q[(++ Q->front)% Q->QSize];
}

int IsEmptyQ(Queue Q)
{
	return Q->front == Q->rear ;
}

 

你可能感兴趣的:(11-散列4 Hashing - Hard Version)