哈希表系统学习及 例题汇总 案例 day9

1. C ,链表, 实现哈希表的删除,插入,添加,查询功能

(适合频繁的删除插入等操作)

#include <stdio.h>
#include<iostream>
#include<cstring>
#include < vector> 
//#include "hash1.h"
using namespace std;

#define DEFAULT_SIZE 16
int COUNT = 0;

typedef struct _ListNode
{
	int key;
	void* data;
	struct _ListNode* next;
}ListNode;

typedef ListNode* List;   //为一种数据类型定义一个新名字
typedef ListNode* Element;

typedef struct _HashTable
{
	int TableSize;
	List* Thelists;
}HashTable;

int myHash(int key, int TableSize)
{
	return (key % TableSize);
}



HashTable* InitHash(int TableSize);
Element Find(HashTable* HashTable, int present_key);
void Insert(HashTable* HashTable, int present_key, void* present_value);
void* Retrieve(Element e);
void Delete(HashTable* HashTable, int present_key, void* present_value); //哈希表元素删除


//初始化哈希表
HashTable* InitHash(int TableSize)
{
	int i = 0;
	HashTable* hTabel = NULL;

	if (TableSize <= 0)
	{
		TableSize = DEFAULT_SIZE;
	}

	hTabel = (HashTable*)malloc(sizeof(HashTable));
	if (hTabel == NULL)
	{
		printf("HashTable malloc error \n");
		return NULL;
	}

	hTabel->TableSize = TableSize;

	//为哈希桶的第一个元素分配内存,其为一个指针数组
	hTabel->Thelists = (List*)malloc(sizeof(List) * TableSize);
	if (NULL == hTabel->Thelists)
	{
		printf("HashTable malloc error \n");
		free(hTabel);
		return NULL;
	}

	//为哈希桶对应的指针数组初始化链表节点
	for (int i = 0; i < TableSize; i++)
	{
		hTabel->Thelists[i] = (ListNode *)malloc(sizeof(ListNode));
		if (NULL == hTabel->Thelists[i])
		{
			printf("HashTable malloc error \n");
			free(hTabel->Thelists);
			free(hTabel);
			return NULL;
		}
		else
		{
			memset(hTabel->Thelists[i], 0, sizeof(ListNode));  //把分配的内存里面的东西都设置为0
		}
	}
	return hTabel;
}

//会根据键值查找元素
Element Find(HashTable* HashTable, int present_key)
{
	int i = 0;
	List L = NULL;
	Element e = NULL;
	i = myHash(present_key, HashTable->TableSize);  //计算当前的元素对应的键指在第几个分类数组里
	L = HashTable->Thelists[i];  //将找到的数组的索引给L,也即时数组的头节点
	e = L->next;
	while (e != NULL && e->key != present_key)
		e = e->next;

	return e;
}

//向哈希表插入元素,void* present_value:可以擦汗如任意形式的键值
void Insert(HashTable* HashTable, int present_key, void* present_value)
{
	Element e = NULL, temp = NULL;
	List L = NULL;
	e = Find(HashTable, present_key);

	if (e == NULL)
	{
		temp = (Element)malloc(sizeof(ListNode));
		if (temp == NULL)
		{
			printf(" malloc error \n");
		}

		//判断当前键值在第几个数组myHash(present_key, HashTable->TableSize)
		//对应的就是键值所在数组的地址,也即是第一个元素的地址
		L = HashTable->Thelists[myHash(present_key, HashTable->TableSize)];  
		//前插法
		temp->data = present_value;
		temp->key = present_key;
		temp->next = L->next;
		L->next = temp;

		COUNT += 1;
	}
	else
	{
		printf(" key is already exist \n");
	}
}

//哈希表元素删除
void Delete (HashTable* HashTable, int present_key, void* present_value)
{
	Element e = NULL, previous = NULL;
	List L = NULL;
	int i = myHash(present_key, HashTable->TableSize);
	//将此节点指向索引值所在数组的第一个元素
	L = HashTable->Thelists[i];

	previous = L;
	e = L->next;
	while(e != NULL && e->key != present_key)
	{
		previous = e;   //记录前一个节点
		e = e->next;
	}

	if (e)  //如果键值存在
	{
		previous->next = e->next;
		free(e);
	}
}

//哈希表元素提取
void* Retrieve(Element e)
{
	return e ? e->data : NULL;
}

void Print(HashTable* HashTable)
{
	if (HashTable == NULL)
	{
		printf(" Table is empty \n");
	}
	else
	{
		for (int i = 1; i <= COUNT; i++)
		{
			
			Element e= Find(HashTable, i);
			if (e)
			{
				printf("key = %d\n", i);
				printf("value = %s\n", (const  char*)Retrieve(e));
			}
			else
			{
				printf("key = %d not found\n",i);
			}
			
		}
	}
	printf("******************** finish\n");
}

int main()
{
	const  char *elems[] = { "翠花","小芳","苍老师" };  //指针数组

	HashTable* HashTable = NULL;
	HashTable = InitHash(30);
	Insert(HashTable, 1, (char*)elems[0]);
	Insert(HashTable, 2, (char*)elems[1]);
	Insert(HashTable, 3, (char*)elems[2]);

	Print(HashTable);

	Delete(HashTable,2, (char*)elems[1]);
	Print(HashTable);
	return 0;
}

2 C数组实现 哈希表删除,插入等等功能

(适合长度固定,数据一次性给完,数据比较少的情况)

3 例题汇总

(1)原地哈希 442数组中的重复元素

https://blog.csdn.net/weixin_43528481/article/details/129916692?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22129916692%22%2C%22source%22%3A%22weixin_43528481%22%7D

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值