哈希三部曲:二:第一部分:C语言实现 静态哈希表

在这个静态哈希表中

我们用一个容量为10 的静态数组作为哈希表的底层构造

但是数组的每一个存储空间中又分为两个部分

                                数据区:data

                                                  记录所存储的数据

                                状态区:state

                                                      状态区主要记录这个空间的状态;分别为:EXIST:表示这个位置已经存有元素

                                                                                                                   EMPTY:表示这个位置为空

                                                                                                              DELET:表示这个位置存的元素是无效的被删除的元素

新建头文件;HashTable.h

底层构建:

#pragma once

////////////////////////静态哈希表///////////////////////////////////

#define MAX_SIZE 10

typedef int DataType;

typedef enum {EXIST,EMPTY,DELET}State;

typedef struct HTElem
{
	DataType _data;     //数据
	State _state;       //状态
}HTElem;

typedef struct HashTable
{
	HTElem _array[MAX_SIZE];
	int _size;                  //记录哈希表格中有效元素个数
	int _total;                 //哈希表中总元素个数:包含状态为 存在的和删除的
	int _IsLineDetective;       //是否是线性探测
	int _capacity;
}HT;

void HashTableInit(HT *ht,int capacity,int IsLineDetective);   //初始化
void HashTableInsert(HT *ht, DataType data);                   //插入元素
void HashTableDelet(HT *ht, DataType data);                    //删除元素
int HashTableFind(HT *ht, DataType data);                      //查询
int HashTableSize(HT *ht);                                     //求有效元素个数
int HashTableEmpty(HT *ht);                                    //判空                                   
void PrintfHashBucket(HT* ht);                                 //打印

操作函数

#include<stdio.h>
#include<windows.h>
#include<assert.h>

int HashFunc(DataType data)        //获得哈希地址  ( 插入和查询时使用 ) 
{
	return data % MAX_SIZE;       //除留余数法
}


int DetectiveLine(int hashAddr)            //线性探测  ( 插入和查询时使用 )
{
     hashAddr++;
	
if (hashAddr == MAX_SIZE)             // 处理越界 如果地址走到末尾,则又回到起始位置;
     hashAddr = 0;

return hashAddr;
}

int Detective2(int hashAddr, int i)        //二次探测   ( 插入和查询时使用 )   
{
	hashAddr = hashAddr + 2 * i + 1;            

	if (hashAddr >= MAX_SIZE)               //  处理越界  
	hashAddr %= MAX_SIZE;             

	return hashAddr;
}

void HashTableInit(HT *ht,int capacity,int IsLineDetective)    //初始化
{
	int i = 0;
	for (; i < MAX_SIZE; ++i)
		ht->_array[i]._state = EMPTY;

	ht->_size = 0;
	ht->_total = 0;
	ht->_capacity = capacity;
	ht->_IsLineDetective = IsLineDetective;
}

void HashTableInsert(HT *ht, DataType data)        //插入
{
	int hashAddr = 0;
	int i = 0;
	assert(ht);

	if (ht->_total == MAX_SIZE)    //空间已满
	return;

	//计算哈希地址
	hashAddr = HashFunc(data);


	while (EMPTY != ht->_array[hashAddr]._state)
	{
		//如果当前哈希地址上已经有了元素
		if (EXIST == ht->_array[hashAddr]._state)  
		{
			if (data == ht->_array[hashAddr]._data)  
				return;               //如果当前位置上已经有了相同的元素;则不再重复插入
		}

		//需要找下一个空位置
		if (ht->_IsLineDetective)
			hashAddr=DetectiveLine(hashAddr);     //以线性探测法找
		else
			hashAddr =Detective2(hashAddr, ++i);  //以二次探测法找
	}

    //对找到的哈西地址进行插入元素
	ht->_array[hashAddr]._data = data;
	ht->_array[hashAddr]._state = EXIST;
	ht->_size++;
	ht->_total++;
}

void HashTableDelete(HT * ht, DataType data)        //删除
{
	int ret = -1;
	assert(ht);

	ret = HashTableFind(ht, data);
	if(-1 !=ret)

	{
		ht->_array[ret]._state = DELET;
		ht->_size--;
	}
}

int HashTableFind(HT *ht, DataType data)   //从当前哈希地址找到下一个空位置
{
	int hashAddr = -1,   starAddr = -1;  //开始查找的起始位置
	int i = 0;
	assert(ht);

	hashAddr = HashFunc(data);               //哈希地址
	starAddr = hashAddr;

	while (EMPTY != ht->_array[hashAddr]._state)     //看地址内是否有数据
	{
		if (EXIST == ht->_array[hashAddr]._state)        //看当前地址的状态
		{
			if (data == ht->_array[hashAddr]._data)         //看数据是否是我们查找的
				return hashAddr;
		}

		//到此说明在求得的哈西地址内没有找到我们需要的数据,那么就继续往后找;

		if (ht->_IsLineDetective)               
		{
			hashAddr=DetectiveLine(hashAddr);          //以线性探测法找
			
			if (hashAddr == starAddr)    //找了一圈,又回到起始位置  都没有找到
				  return -1;
		}
		else
			hashAddr=Detective2(hashAddr, ++i);        //以二次探测法找
	}
	return -1;
}

int HashTableSize(HT *ht)
{
	assert(ht);
	return ht->_size;
}

int HashTableEmpty(HT *ht)
{
	assert(ht);
	return 0 == ht->_size;
}

void PrintfHashBucket(HT* ht)        //打印
{
	int i = 0;
	for (; i < ht->_capacity; i++)
	{
		if (EXIST == ht->_array[i]._state)
      printf("哈希地址为%d的数据为:%d\n", i, ht->_array[i]._data);
	}
}

进行测试

新建源文件:Hash.c

#include"HashTable.h"


int main()
{

    HT ht;

	HashTableInit(&ht, 10, 1);   //初始化

	HashTableInsert(&ht, 1);
	HashTableInsert(&ht, 4);
	HashTableInsert(&ht, 6);
	HashTableInsert(&ht, 5);
	HashTableInsert(&ht, 3);
	HashTableInsert(&ht, 15);

	PrintfHashBucket(&ht);

	printf("size为:%d  \n", HashTableSize(&ht));

	HashTableDelete(&ht, 3);

	PrintfHashBucket(&ht);

	printf("size为:%d  \n", HashTableSize(&ht));


	system("pause");
	return 0;
}

运行结果:

哈希地址为1的数据为:1
哈希地址为3的数据为:3
哈希地址为4的数据为:4
哈希地址为5的数据为:5
哈希地址为6的数据为:6
哈希地址为7的数据为:15
size为:6
哈希地址为1的数据为:1
哈希地址为4的数据为:4
哈希地址为5的数据为:5
哈希地址为6的数据为:6
哈希地址为7的数据为:15
size为:5
请按任意键继续. . .

猜你喜欢

转载自blog.csdn.net/mowen_mowen/article/details/82943371