哈希表——拉链法

一、Hash.h

#ifndef __HASH_H__
#define __HASH_H__

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

typedef int KeyType;

typedef struct HashNode
{
	KeyType _key;
	struct HashNode* _next;
}HashNode;

typedef struct HashTable
{
	HashNode** _tables; //指针数组
	size_t _size;
	size_t _capacity;
}HashTable;

HashNode* BuyHashNode(KeyType key);
size_t HashFunc(HashTable* ht, KeyType key);
static size_t GetNextPrimeNum(HashTable* ht);

void HashTableInit(HashTable* ht, size_t Initsize);
int HashTableInsert(HashTable* ht, KeyType key);
HashNode* HashTableFind(HashTable* ht, KeyType key);
int HashTableRemove(HashTable* ht, KeyType key);
void HashTablePrint(HashTable* ht);
void HashTableDestory(HashTable* ht);

#endif __HASH_H__

二、Hash.cpp

#define _CRT_SECURE_NO_WARNINGS 1

#include "Hash.h"

//初始化
void HashTableInit(HashTable* ht, size_t Initsize)
{
	assert(ht);
	ht->_tables = (HashNode**)malloc(Initsize*sizeof(HashNode*));
	assert(ht->_tables);
	ht->_size = 0;
	ht->_capacity = Initsize;
	for (size_t i = 0; i < ht->_capacity; i++)
	{
		ht->_tables[i] = NULL;
	}
}

//销毁
void HashTableDestory(HashTable* ht)
{
	assert(ht);
	for (size_t index = 0; index < ht->_capacity; index++) //先销毁每一个链表
	{
		HashNode* cur = ht->_tables[index];
		while (cur)
		{
			HashNode* next = cur->_next;
			free(cur);
			cur = NULL;
			cur = next;
		}
	}
	free(ht->_tables); //再销毁顺序表
	ht->_tables = NULL;
	ht->_size = ht->_capacity = 0;
}

//哈希函数-查找位置
size_t HashFunc(HashTable* ht, KeyType key)
{
	return key % ht->_capacity;
}

//素数表
static size_t GetNextPrimeNum(HashTable* ht)
{
	const int _PrimeSize = 28;
	static const unsigned long _PrimeList[_PrimeSize] =
	{
		53ul, 97ul, 193ul, 389ul, 769ul,
		1543ul, 3079ul, 6151ul, 12289ul,
		24593ul, 49157ul, 98317ul, 196613ul,
		393241ul, 786433ul, 1572869ul, 3145739ul,
		6291469ul, 12582917ul, 25165843ul, 50331653ul,
		100663319ul, 201326611ul, 402653189ul, 805306457ul,
		1610612741ul, 3221225473ul, 4294967291ul
	};
	int index = 0;
	while (index < _PrimeSize)
	{
		if (ht->_capacity < _PrimeList[index])
		{
			return _PrimeList[index];
		}
		index++;
	}
	return _PrimeList[_PrimeSize - 1];
}

//扩容
void Checkcapacity(HashTable* ht)
{
	assert(ht);
	if (ht->_size == ht->_capacity) //将载荷因子控制在1
	{
		HashTable newht; //新建一个哈希表
		HashTableInit(&newht, GetNextPrimeNum(ht));
		for (size_t i = 0; i < ht->_capacity; i++)
		{
			HashNode* cur = ht->_tables[i];
			while (cur)
			{
				HashNode* next = cur->_next; //保存下一个节点
				size_t index = HashFunc(&newht, cur->_key); //重新计算原哈希表中每一个key在新哈希表中的位置
				 //利用原来已开辟的空间来进行链接,不用再重新开辟空间
				cur->_next = newht._tables[index];		
				newht._tables[index] = cur;
				cur = next;
			}
			ht->_tables[i] = NULL;
		}
		free(ht->_tables); //销毁原哈希表
		ht->_tables = newht._tables; //更新哈希表
		ht->_capacity = newht._capacity;
	}
}

//创建结点
HashNode* BuyHashNode(KeyType key)
{
	HashNode* newnode = (HashNode*)malloc(sizeof(HashNode));
	assert(newnode);
	newnode->_key = key;
	newnode->_next = NULL;
	return newnode;
}

//插入
int HashTableInsert(HashTable* ht, KeyType key)
{
	assert(ht);
	Checkcapacity(ht);
	size_t index = HashFunc(ht, key);
	HashNode* cur = ht->_tables[index];
	while (cur)
	{
		if (cur->_key == key)
		{
			return 0;
		}
		cur = cur->_next;
	}
	HashNode* newnode = BuyHashNode(key);
	newnode->_next = ht->_tables[index];
	ht->_tables[index] = newnode;
	ht->_size++;
	return 1;
}

//查找
HashNode* HashTableFind(HashTable* ht, KeyType key)
{
	assert(ht);
	size_t index = HashFunc(ht, key);
	HashNode* cur = ht->_tables[index];
	while (cur)
	{
		if (cur->_key == key)
		{
			return cur;
		}
		cur = cur->_next;
	}
	return NULL;
}

//删除
int HashTableRemove(HashTable* ht, KeyType key)
{
	assert(ht);
	size_t index = HashFunc(ht, key);
	HashNode* cur = ht->_tables[index];
	if (cur == NULL)
	{
		return 0;
	}
	else if (cur->_next == NULL)
	{
		if (cur->_key == key)
		{
			free(cur);
			ht->_tables[index] = NULL;
			ht->_size--;
			return 1;
		}
		return 0;
	}
	else
	{
		HashNode* prev = ht->_tables[index];
		while (cur)
		{
			if (cur->_key == key)
			{
				prev->_next = cur->_next;
				free(cur);
				cur = NULL;
				ht->_size--;
				return 1;
			}
			prev = cur;
			cur = cur->_next;
		}
		return 0;
	}	
}

//打印
void HashTablePrint(HashTable* ht)
{
	assert(ht);
	printf("\n");
	for (size_t index = 0; index < ht->_capacity; index++)
	{
		HashNode* cur = ht->_tables[index];
		while (cur)
		{
			printf("%d->", cur->_key);
			cur = cur->_next;
		}
		printf("NULL\n");
	}
	printf("\n");
}

三、Test.cpp

#define _CRT_SECURE_NO_WARNINGS 1

#include "Hash.h"

int main()
{
	HashTable ht;
	HashTableInit(&ht, 5);
	int arr[] = { 10, 20, 30, 40, 50 };

	for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
	{
		HashTableInsert(&ht, arr[i]);
	}
	HashTablePrint(&ht);

	HashNode* cur = HashTableFind(&ht, 1);
	if (cur)
	{
		printf("找到:%d\n", cur->_key);
	}
	else
	{
		printf("未找到\n");
	}

	HashTableInsert(&ht, 1);
	HashTableInsert(&ht, 2);
	HashTableInsert(&ht, 3);
	HashTableInsert(&ht, 4);
	HashTablePrint(&ht);

	cur = HashTableFind(&ht, 1);
	if (cur)
	{
		printf("找到:%d\n", cur->_key);
	}
	else
	{
		printf("未找到\n");
	}

	HashTableRemove(&ht, 1);
	HashTablePrint(&ht);

	cur = HashTableFind(&ht, 1);
	if (cur)
	{
		printf("找到:%d\n", cur->_key);
	}
	else
	{
		printf("未找到\n");
	}

	HashTableDestory(&ht);

	system("pause");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值