【数据结构与算法】哈希表——字符串匹配

大家好,这里是国中之林!
❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看←

一.引入

原来我们讲的都是以整数作为关键码,那么我们可不可以用字符串来作为关键码呢?
有的时候我们希望能够很快的查找字符串.
那么如果我们也想用哈希表存储,我们该怎么办呢?
答案是基本思想还是不变,哈希函数求余来进行分组.
但是字符串怎么可能求取呢?
那么就需要我们进行转换了,就是大名鼎鼎的SDBM算法

二.哈希表结构

跟原来一样,只不过关键码的类型不在是整型了,c++中的字符串是const char*,所以这里用的const void*.
在这里插入图片描述

三.SDBMHash算法(字符->数字)★

可以将不同的字符串转换成为不同的数字,就方便我们进行取余分组了.
在这里插入图片描述

四.哈希表的算法实现

1.哈希函数

先将字符串转换为数字再取余进行操作.
在这里插入图片描述

2.初始化

HashTable* initHash(int TableSize)
{
	int i = 0;
	HashTable* hTable = NULL;
	if (TableSize <= 0)
	{
		TableSize = DEFAULT_SIZE;
	}

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

	hTable->TableSize = TableSize;

	hTable->Thelists = (List*)malloc(sizeof(List) * TableSize);
	if (hTable->Thelists == NULL)
	{
		printf("HashTable malloc error\n");
		free(hTable);
		return NULL;
	}

	for (i = 0; i < hTable->TableSize; i++)
	{
		hTable->Thelists[i] = (ListNode*)malloc(sizeof(ListNode));
		if (NULL == hTable->Thelists[i])
		{
			printf("HashTable malloc error\n");
			free(hTable->Thelists);
			free(hTable);
			return NULL;
		}
		else
		{
			memset(hTable->Thelists[i], 0, sizeof(ListNode));
		}
	}
	return hTable;
}

3.查找

在这里插入图片描述

4.插入

void insert(HashTable* HashTable, const void* key, const void* value)
{
	Element e = NULL, tmp = NULL;
	List L = NULL;
	e = Find(HashTable, key);
	if (e == NULL)
	{
		tmp = (Element)malloc(sizeof(ListNode));
		if (tmp == NULL)
		{
			printf("malloc error\n");
			return;
		}

		int code = Hash(key, HashTable->TableSize);
		L = HashTable->Thelists[code];
		tmp->data = value;
		tmp->key = key;
		tmp->next = L->next;
		L->next = tmp;
	}
	else
	{
		printf("the key already exist\n");
	}
}

5.删除

在这里插入图片描述

6.获取数据

在这里插入图片描述

7.销毁

在这里插入图片描述
这是关键码的类型改变了一下,其他都一样,就不讲了.

五.完整代码

1.头文件

#pragma once

#define DEFAULT_SIZE 16

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

typedef ListNode* List;
typedef ListNode* Element;

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


2.源文件

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hash_table.h"

#define BUCKET_SIZE 1024

#define compare(a,b) strcmp((const char*)a,(const char*)b)
#define hash_func    SDBMHash

unsigned int SDBMHash(const void* key)
{
	unsigned int hash = 0;
	char* str = (char*)key;

	while (*str) 
	{
		hash = (*str++) + (hash << 6) + (hash << 16) - hash;
	}
	return (hash & 0x7FFFFFFF);
}

int Hash(const void* key, int TableSize)
{
	return hash_func(key) % TableSize;
}

HashTable* initHash(int TableSize)
{
	int i = 0;
	HashTable* hTable = NULL;
	if (TableSize <= 0)
	{
		TableSize = DEFAULT_SIZE;
	}

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

	hTable->TableSize = TableSize;

	hTable->Thelists = (List*)malloc(sizeof(List) * TableSize);
	if (hTable->Thelists == NULL)
	{
		printf("HashTable malloc error\n");
		free(hTable);
		return NULL;
	}

	for (i = 0; i < hTable->TableSize; i++)
	{
		hTable->Thelists[i] = (ListNode*)malloc(sizeof(ListNode));
		if (NULL == hTable->Thelists[i])
		{
			printf("HashTable malloc error\n");
			free(hTable->Thelists);
			free(hTable);
			return NULL;
		}
		else
		{
			memset(hTable->Thelists[i], 0, sizeof(ListNode));
		}
	}
	return hTable;
}

Element Find(HashTable* HashTable, const void* key)
{
	int i = 0;
	List L = NULL;
	Element e = NULL;
	i = Hash(key, HashTable->TableSize);
	L = HashTable->Thelists[i];
	e = L->next;
	while (e!=NULL&&compare(e->key,key)!=0)
	{
		e = e->next;
	}
	return e;
}

void insert(HashTable* HashTable, const void* key, const void* value)
{
	Element e = NULL, tmp = NULL;
	List L = NULL;
	e = Find(HashTable, key);
	if (e == NULL)
	{
		tmp = (Element)malloc(sizeof(ListNode));
		if (tmp == NULL)
		{
			printf("malloc error\n");
			return;
		}

		int code = Hash(key, HashTable->TableSize);
		L = HashTable->Thelists[code];
		tmp->data = value;
		tmp->key = key;
		tmp->next = L->next;
		L->next = tmp;
	}
	else
	{
		printf("the key already exist\n");
	}
}

void Delete(HashTable* HashTable, void* key)
{
	Element e = NULL, last = NULL;
	List L = NULL;
	int i = Hash(key, HashTable->TableSize);
	L = HashTable->Thelists[i];
	e = L->next;
	while (e!=NULL&&e->key!=key)
	{
		last = e;
		e = e->next;
	}

	if (e)
	{
		last->next = e->next;
		free(e);
	}
}

const void* Retrieve(Element e)
{
	return e ? e->data : NULL;
}

void Destory(HashTable* HashTable)
{
	int i = 0;
	List L = NULL;
	Element cur = NULL, next = NULL;
	for (i = 0; i < HashTable->TableSize; i++)
	{
		L = HashTable->Thelists[i];
		cur = L->next;
		while (cur!=NULL)
		{
			next = cur->next;
			free(cur);
			cur = next;
		}
		free(L);
	}
	free(HashTable->Thelists);
	free(HashTable);
}


void main(void)
{
	const char* elems[] = { "ADBB","BDDC","CDBC","BDBB" };
	const char* tester = "ABDBBBAC";
	char cur[5] = { '\0' };
	HashTable* HashTable = NULL;
	HashTable = initHash(BUCKET_SIZE);
	for (int i = 0; i < sizeof(elems) / sizeof(elems[0]); i++)
	{
		insert(HashTable, elems[i], elems[i]);
	}

	strncpy_s(cur, tester + 1, 4);//BDBB'\0'

	Element e = Find(HashTable, cur);
	if (e)
	{
		printf("存在基因片段:%s 为色盲!\n", (const char*)Retrieve(e));
	}
	else
	{
		printf("Not found [key:%s]\n", cur);
	}

	system("pause");
}

3.运行结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值