/// 11_15.cpp: 编写对一组关键字,利用链地址法解决冲突,
/// 散列函数为H(k),写出在此散列表中插入、删除元素的算法
#include "stdafx.h"
#include <stdlib.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include "Chapter11.h"
void printDataType(const dataType data)
{
printf("%c", data);
}
void printKeyType(const keyType key)
{
printf("%2d", key);
}
keyType getHash(const dataType data)
//从data算出hash值的函数
//使用简单的除留余数法
{
keyType hash = EMPTY_KEY;
hash = data % MODDER;
return hash;
}
hashChain* newHashChain()
//分配新的hashChain节点的函数
{
hashChain* head = NULL;
head = (hashChain*)malloc(sizeof(hashChain));
if(head == NULL)
{
printf("分配空间出错!/n");
exit(1);
}
initializeHashChain(head);
return head;
}
void initializeHashChain(hashChain* chain)
//初始化一个hashChain节点的函数
{
chain->data = EMPTY_CHAR;
chain->pNext = NULL;
}
void initializeHashNodes(hashNode* head, const int size)
//初始化一个hashNode表的函数
{
for (int i = 0; i < size; i++)
{
(head + i)->key = i;
(head + i)->pChain = NULL;
}
}
hashNode* chainSearch(hashNode* head, const int size, const dataType data)
//在以head为首,长度为size的hashNode表中查找key,并返回其hashNode地址的函数
//不成功则返回NULL
{
hashChain* chain = NULL;
hashNode* temp = head;
if (head == NULL)
{
return NULL;
}
keyType tempKey = getHash(data);
if (tempKey >= size)
{
return NULL;
}
for (int i = 0; i < size; i++)
{
if ( (head + i)->key == tempKey )
{
return (head + i);
}
}
return NULL;
//在整个散列表中都找不到所需要的散列数据,返回NULL
}
void printHashTable(hashNode* head, const int size)
//显示以head为首,长度为size的hashNode表的内容的函数
{
hashNode* tempHead = head;
if (tempHead == NULL)
{
printf("该散列表没有内容!/n");
return;
}
printf("散列表的内容是:/n");
printf("散列值/t/t数据内容/n");
//表头
hashChain* tempChain = NULL;
for (int i = 0; i < size; i++)
{
tempHead = head + i;
tempChain = tempHead->pChain;
printf(" ");
printKeyType(tempHead->key);
printf("/t");
while (tempChain != NULL)
{
printf("->");
printDataType(tempChain->data);
printf("/t");
tempChain = tempChain->pNext;
}
printf("/n");
}
}
void freeHashTable(hashNode* head, const int size)
//释放以head为首,长度为size的hashNode表所占用的空间的函数
{
hashNode* tempHead = head;
hashChain* r = NULL;
hashChain* s = NULL;
for (int i = 0; i < size; i++)
{
r = (tempHead + i)->pChain;
if ( r == NULL)
{
continue;
}
s = r->pNext;
if (s == NULL)
{
free(r);
r = NULL;
continue;
}
while (s != NULL)
{
free(r);
r = NULL;
r = s;
s = s->pNext;
}
}
}
hashNode* createHashTable(hashNode* head, const int size, const int totalNumber)
//建立初始长度为size的散列表,并返回其首地址的函数
//不成功则返回NULL
{
if (head == NULL)
{
head = (hashNode*)malloc( sizeof(hashNode) * size);
}
srand( (unsigned)time(NULL) );
char tempData = 'a';
char tempBase = 'a';
int random = 0;
for (int i = 0; i < totalNumber; i++)
{
do
{
random = rand();
switch(random % 3)
{
case 0:
tempBase = '!';
//'!'是能显示的ASCII码的最小值
break;
case 1:
tempBase = 'a';
break;
case 2:
tempBase = 'A';
break;
default:
printf("/n/n函数createHashTable中的switch语句处理有误,需要修正!/n/n");
break;
}
tempData = ( random % 31 ) + tempBase;
//在tempBase基础上加一个0到30的数作为数据
//之所以用30是因为'A'的ASCII码是97,而
//char类型的上限是127
}
while(insertIntoChain(head, size, tempData) == NULL);
}
return head;
}
hashChain* insertIntoChain(hashNode* head, const int size, const dataType source)
//在以head为首,长度为size的hashNode表中插入值为source的节点的函数
//成功则返回其地址,否则返回NULL
//如果未进行插入,则返回NULL
{
hashNode* oriNode = chainSearch(head, size, source);
hashChain* newChain = newHashChain();
newChain->data = source;
hashChain* temp = NULL;
if (oriNode == NULL)
//不做任何处理
{
printf("/n/n函数insertIntoChain中的oriNode值为空,需要修正!/n/n");
return NULL;
}
if (oriNode->pChain == NULL)
//chainNodes中不含有key和source相匹配的数据
//只需直接将chain连接到相应的key处即可返回
{
oriNode->pChain = newChain;
}
else
//chainNodes中已经含有和key和source相匹配的数据
//需要将newChain插入oriNode->pChain
{
temp = oriNode->pChain;
while (temp != NULL)
{
if (temp->data == source)
{
free(newChain);
return NULL;
//已存在source,不进行操作,返回NULL
}
temp = temp->pNext;
}
temp = oriNode->pChain;
oriNode->pChain = newChain;
newChain->pNext = temp;
}
return newChain;
}
int main(int argc, char* argv[])
{
hashNode hashNodes[HASH_TABLE_LENGTH];
hashNode* head = hashNodes;
initializeHashNodes( head, HASH_TABLE_LENGTH );
//对散列表进行初始化
int totalNumber = 0;
char ch = 'y';
while(ch == 'y' || ch == 'Y')
{
do
{
printf("请输入散列表中的元素数(现在散列表的总长度是%d)/n为了尽可能地减少出错机会,请输入一个不大于90的正整数:"
, HASH_TABLE_LENGTH);
scanf("%2d", &totalNumber);
}
while(totalNumber < 0 || totalNumber > 90);
head = createHashTable(head, HASH_TABLE_LENGTH, totalNumber);
printHashTable(head, HASH_TABLE_LENGTH);
printf("/n还继续吗(请输入y以继续)?");
ch = getche();
printf("/n");
freeHashTable(head, HASH_TABLE_LENGTH);
}
return 0;
}