C源码@数据结构与算法->Hashing

/*
 * testhash.cpp
 */
#define QuadProb		/* Define the appropriate hash algorithm */

#include
  
  
   
   

#ifdef SepChain
#include "hashsep.h"
#endif

#ifdef QuadProb
#include "hashquad.h"
#endif

#define NumItems (400)

int main()
{
	HashTable H;
	Position P;
	int i, j, CurrentSize;

	H = InitializeTable(CurrentSize = 13);

	for (i = 0, j = 0; i < NumItems; ++i, j += 71)
	{
#ifdef QuadProb
		if (i > CurrentSize / 2)
		{
			H = Rehash(H);
			printf("Rehashing...\n");
			CurrentSize *= 2;
		}
#endif
		Insert(j, H);
	}

	for (i = 0, j = 0; i < NumItems; ++i, j += 71)
	{
#ifdef SepChain
		if ((P = Find(j, H)) == NULL || Retrieve(P) != j)
#endif
#ifdef QuadProb
		if (Retrieve((P = Find(j, H)), H) != j)
		{
			printf("Error at %d\n", j);
		}
		
#endif
	}

	printf("End of program.\n");

	return 0;
}
  
  

/*
 * fatal.h
 */
#include 
   
   
    
    
#include 
    
    
     
     

#define Error(Str)		FatalError(Str)
#define FatalError(Str)	fprintf(stderr, "%s\n", Str), exit(-1)	
    
    
   
   
/*
 * hashsep.h
 */
#ifndef _HASHSEP_H
#define _HASHSEP_H

#ifndef NULL
#define NULL (0)
#endif

typedef int ElementType;
typedef unsigned int Index;

struct ListNode;
typedef struct ListNode *Position;
struct HashTbl;
typedef struct HashTbl *HashTable;

#ifdef __cplusplus
extern "C" {
#endif

HashTable InitializeTable(int TableSize);
Index Hash(ElementType Key, int TableSize);
Position Find(ElementType Key, HashTable H);
void Insert(ElementType Key, HashTable H);
ElementType Retrieve(Position P);
void DestroyTable(HashTable H);
void PrintElements(HashTable H);

#ifdef __cplusplus
}
#endif

#endif	/* _HASHSEP_H */
/*
 * hashsep.cpp
 */
#include 
   
   
    
    
#include 
    
    
     
     
#include "fatal.h"
#include "hashsep.h"

#define MinTableSize (10)

struct ListNode
{
	ElementType Element;
	Position Next;
};

typedef Position List;

/*
 * List *TheLists will be an array of lists, allocated later.
 * The lists use headers(for simplicity), though this waste space.
 */
struct HashTbl
{
	int TableSize;
	List *TheLists;
};

/*
 * Return next prime; assume N >= 10.
 */
static int NextPrime(int N)
{
	int i;

	if (N % 2 == 0)
	{
		++N;
	}
	for ( ; ; N += 2)
	{
		for (i = 3; i * i <= N; i += 2)
		{
			if (N % i == 0)
			{
				goto ContOuter;		/* Sorry about this! */
			}
		}
		return N;
	ContOuter:;
	}
}


HashTable InitializeTable(int TableSize)
{
	HashTable H;
	int i;

	if (TableSize < MinTableSize)
	{
		FatalError("Table size too small!");
	}

	H = (HashTable)malloc(sizeof(struct HashTbl));
	if (H == NULL)
	{
		FatalError("Out of space!");
	}

	H->TableSize = NextPrime(TableSize);

	/* Allocate array of lists */
	H->TheLists = (List *)malloc(sizeof(List)* H->TableSize);
	if (H->TableSize == NULL)
	{
		FatalError("Out of space!");
	}

	/* Allocate list headers */
	for (i = 0; i < H->TableSize; ++i)
	{
		H->TheLists[i] = (List)malloc(sizeof(struct ListNode));
		if (H->TheLists[i] == NULL)
		{
			FatalError("Out of space!");
		}
		else
		{
			H->TheLists[i]->Next = NULL;
		}
	}

	return H;
}

/*
 * Hash function for ints
 */
Index Hash(ElementType Key, int TableSize)
{
	return Key % TableSize;
}

Position Find(ElementType Key, HashTable H)
{
	Position P;
	List L;

	L = H->TheLists[Hash(Key, H->TableSize)];
	P = L->Next;
	while (P != NULL && P->Element != Key)
	{
		P = P->Next;
	}

	return P;
}

/*
 * Place the item at the front of the list.
 */
void Insert(ElementType Key, HashTable H)
{
	Position Pos, NewCell;
	List L;

	Pos = Find(Key, H);
	if (Pos == NULL)	/* Key is not found */
	{
		NewCell = (List)malloc(sizeof(ListNode));
		if (NewCell == NULL)
		{
			FatalError("Out of space!");
		}
		else
		{
			L = H->TheLists[Hash(Key, H->TableSize)];
			NewCell->Next = L->Next;
			L->Next = NewCell;
			NewCell->Element = Key;
		}
	}
}

ElementType Retrieve(Position P)
{
	return P->Element;
}

void DestroyTable(HashTable H)
{
	Position P, Tmp;
	int i;

	for (i = 0; i < H->TableSize; ++i)
	{
		P = H->TheLists[i];
		while (P != NULL)
		{
			Tmp = P->Next;
			free(P);
			P = Tmp;
		}
	}

	free(H->TheLists);
	free(H);
}

void PrintElements(HashTable H)
{
	Position P;
	List L;

	for (int i = 0; i < H->TableSize; ++i)
	{
		L = H->TheLists[i];
		P = L->Next;
		printf("%2d: ", i);
		while (P != NULL)
		{
			printf("%d ", P->Element);
			P = P->Next;
		}
		printf("\n");
	}
}
    
    
   
   
/*
 * hashquad.h
 */
#ifndef _HASHQUAD_H
#define _HASHQUAD_H

#ifndef NULL
#define NULL (0)
#endif

typedef int ElementType;

typedef unsigned int Index;
typedef Index Position;

struct HashTbl;
typedef struct HashTbl *HashTable;

#ifdef __cplusplus
extern "C" {
#endif

HashTable InitializeTable(int TableSize);
Position Find(ElementType Key, HashTable H);
void Insert(ElementType Key, HashTable H);
HashTable Rehash(HashTable H);
ElementType Retrieve(Position P, HashTable H);
void DestroyTable(HashTable H);
void PrintElements(HashTable H);

#ifdef __cplusplus
}
#endif

#endif	/* _HASHQUAD_H */
/*
 * hashquad.cpp
 */
#include 
     
     
      
      
#include 
      
      
       
       
#include "fatal.h"
#include "hashquad.h"

#define MinTablesize (10)

enum KindOfEntry
{
	Legitimate, Empty, Deleted
};

struct HashEntry
{
	ElementType Element;
	enum KindOfEntry Info;
};

typedef struct HashEntry Cell;

/*
 * Cell *TheCells will be an array of HashEntry cells, allocated later.
 */
struct HashTbl
{
	int TableSize;
	Cell *TheCells;
};

/*
 * Return next prime; assume N >= 10.
 */
static int NextPrime(int N)
{
	int i;

	if (N % 2 == 0)
	{
		++N;
	}
	for (;; N += 2)
	{
		for (i = 3; i * i <= N; i += 2)
		{
			if (N % i == 0)
			{
				goto ContOuter;
			}
		}
		return N;
	ContOuter:;
	}
}

Index Hash(ElementType Key, int TableSize)
{
	return Key % TableSize;
}

HashTable InitializeTable(int TableSize)
{
	HashTable H;
	int i;

	if (TableSize < MinTablesize)
	{
		FatalError("Table size too small!");
	}

	/* Allocate table */
	H = (HashTable)malloc(sizeof(struct HashTbl));
	if (H == NULL)
	{
		FatalError("Out of space!");
	}

	H->TableSize = NextPrime(TableSize);

	/* Allocate array of Cells */
	H->TheCells = (Cell *)malloc(sizeof(Cell) * H->TableSize);
	if (H->TheCells == NULL)
	{
		FatalError("Out of space!");
	}

	for (i = 0; i < H->TableSize; ++i)
	{
		H->TheCells[i].Info = Empty;
	}

	return H;
}

Position Find(ElementType Key, HashTable H)
{
	Position CurrentPos;
	int CollisionNum;

	CollisionNum = 0;
	CurrentPos = Hash(Key, H->TableSize);
	while (H->TheCells[CurrentPos].Info != Empty
		&& H->TheCells[CurrentPos].Element != Key)
	{
		CurrentPos += 2 * ++CollisionNum - 1;
		if (CurrentPos >= H->TableSize)
		{
			CurrentPos -= H->TableSize;
		}
	}

	return CurrentPos;
}

void Insert(ElementType Key, HashTable H)
{
	Position Pos;

	Pos = Find(Key, H);
	if (H->TheCells[Pos].Info != Legitimate)
	{
		/* OK to insert here */
		H->TheCells[Pos].Info = Legitimate;
		H->TheCells[Pos].Element = Key;
	}
}

HashTable Rehash(HashTable H)
{
	int i, OldSize;
	Cell *OldCells;

	OldCells = H->TheCells;
	OldSize = H->TableSize;

	/* Get a new, empty table */
	H = InitializeTable(2 * OldSize);

	/* Scan through old table, reinserting into new */
	for (i = 0; i < OldSize; ++i)
	{
		if (OldCells[i].Info == Legitimate)
		{
			Insert(OldCells[i].Element, H);
		}
	}

	free(OldCells);

	return H;
}

ElementType Retrieve(Position P, HashTable H)
{
	return H->TheCells[P].Element;
}

void DestroyTable(HashTable H)
{
	free(H->TheCells);
	free(H);
}

void PrintElements(HashTable H)
{
	int i;

	for (i = 0; i < H->TableSize; ++i)
	{
		if (H->TheCells[i].Info == Legitimate)
		{
			printf("%d ", H->TheCells[i].Element);
		}
	}
	printf("\n");
}
      
      
     
     



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值