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

news2024/11/27 10:30:36

目录

  • 一.引入
  • 二.哈希表结构
  • 三.SDBMHash算法(字符->数字)★
  • 四.哈希表的算法实现
    • 1.哈希函数
    • 2.初始化
    • 3.查找
    • 4.插入
    • 5.删除
    • 6.获取数据
    • 7.销毁
  • 五.完整代码
    • 1.头文件
    • 2.源文件
    • 3.运行结果

一.引入

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

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2035150.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何选择适合自己的编程语言,为什么R是非计算机专业数据分析的最佳选择,五大点告诉你

在如今的数据驱动世界中&#xff0c;编程语言已成为希望在行业中进行数据分析的专业人士不可或缺的技能。对于非计算机专业背景的学者和学生来说&#xff0c;选择适合自己的编程语言可能看似困难。本文将探讨为什么对于那些需要进行本科生论文、研究生论文、或者发表学术成果的…

4款伪原创文章生成器软件,为创作者在线生成原创文章

在当今内容创作需求旺盛的时代&#xff0c;创作者们常常面临着时间紧迫、灵感枯竭等挑战。而伪原创文章生成器软件的出现&#xff0c;为创作者们提供了一定的帮助。以下将为你详细介绍4款具有特色的伪原创文章生成器软件。 1、智媒ai伪原创工具 对于创作者来说&#xff0c;这款…

redis模块和ioredis的注意事项

redis模块和ioredis的注意事项 文章目录 redis模块和ioredis的注意事项前言一、ioredis和redis使用zrange的比较二、出现zrange结果不同的原因总结 前言 node.js在使用redis的时候有两个库可以选择&#xff0c;一个是redis、另一个是ioredis&#xff0c;我一直以来也没有太大关…

小红书js逆向x-s之补环境

请求参数分析 数据文件在homefeed里&#xff0c;直接复制header参数在Convert curl commands 生成python代码跑一下 &#xff08;注意curlconverter生成的respond的输入参数里有一个是json&#xff0c;这个是不对的&#xff0c;需要改为data&#xff09; 结果发现报错&…

netcore-https证书配置

一、新建项目&#xff1a;WebHtpsDemo 二、生成pfx证书 拷贝到项目中 三、修改配置文件appsettings.Development.json {"KestrelSettings": {"IP": "192.168.31.68","Port": 8189,"CerPath": "xxxCert.pfx",&qu…

“艾”公益——微笑行动「文山站」为艾祝福,让笑起舞

艾多美“微笑行动”文山站拉开帷幕 此次爱心帮助71名唇腭裂患儿 重新绽放微笑 ♥ ♥ ♥ 不让笑容留有缺憾 每个孩子都有微笑的权利 艾多美向唇腭裂儿童伸出援手 绽放笑容&#xff0c;拥抱全新的未来 2024年8月6日-8月12日&#xff0c;云南省文山康复医院迎来了艾多美--微笑行动…

C语言典型例题35

《C程序设计教程&#xff08;第四版&#xff09;——谭浩强》 例题3.3 有一函数&#xff1a;y{-1&#xff08;x<0&#xff09;;0(x0);1(x>0);编程序&#xff0c;要求输入一个x值后&#xff0c;输出y值。 代码&#xff1a; //《C程序设计教程&#xff08;第四版&#xff…

PaddleOCR 图片文字提取

PaddleOCR 图片文字提取 需求一.裁剪车牌号码区域二.对车牌小图进行处理三.填充边界四.识别步骤 需求 工作上的一个需求&#xff0c;需要把图片中的车牌号码提取出来。如图&#xff0c;车牌在图片固定位置。开始使用pytesseract&#xff0c;对中文识别特别不友好&#xff0c;毕…

19116 丑数

### 计划 1. **输入处理**&#xff1a;读取输入的正整数 T 和 T 行的正整数 n。 2. **生成丑数**&#xff1a;使用最小堆&#xff08;优先队列&#xff09;生成丑数&#xff0c;确保每次取出的数都是当前最小的丑数。 3. **存储丑数**&#xff1a;将生成的丑数存储在一个数组中…

IO网络编程

思维导图 作业一&#xff1a;使用wasd控制机械臂 #include<myhead.h> #include <termios.h> #define SER_PORT 8888 //与服务器保持一致 #define SER_IP "192.168.0.103" //服务器ip地址 #define CLI_PORT 6666 //客户端…

【网络】TCP拥塞窗口(第六篇)

拥塞窗口&#xff08;Congestion Window&#xff0c;简称cwnd&#xff09;是TCP协议中用于防止网络拥塞的一种重要机制。它是在发送端采用的一种“拥塞避免”算法和“慢速启动”算法相结合的机制&#xff0c;用于控制发送端向网络中注入的数据量&#xff0c;从而避免网络拥塞。…

MySQL数据库介绍及基础操作

目录&#xff1a; 一.数据库介绍 二.数据库分类 三. 数据库的操作 四. 常用数据类型 五. 表的操作 一.数据库介绍 1.文件保存数据有以下几个缺点: 1.1文件的安全性问题 1.2文件不利于数据查询和管理 1.3文件不利于存储海量数据 1.4文件在程序中控制不方便 为了解决上述问题&…

python爬取B站视频实验

实验17&#xff1a;爬虫2 文章目录 实验17&#xff1a;爬虫21.实验目标及要求2. 实验主要内容3.实验小结 1.实验目标及要求 &#xff08;1&#xff09;掌握有关爬虫的包 &#xff08;2&#xff09;掌握爬虫方法 &#xff08;3&#xff09;爬取B站卡塔尔世界杯若干视频 2. 实验…

css实现水滴效果图

效果图&#xff1a; <template><div style"width: 100%;height:500px;padding:20px;"><div class"water"></div></div> </template> <script> export default {data() {return {};},watch: {},created() {},me…

【开端】一个看的奇奇怪怪类的解析

一、绪论 Java中正常的类语法如下&#xff1a; public class TmpMUser implements Serializable{ Data public class TmpMUser implements Serializable{/*** 序列*/private static final long serialVersionUID 1L;/*** */private String rowId;/*** */private String …

贪心算法篇--代码随想录算法训练营第二十七天| 134. 加油站,135. 分发糖果,860.柠檬水找零

134. 加油站 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 讲解视频&#xff1a; 贪心算法&#xff0c;得这么加油才能跑完全程&#xff01;LeetCode &#xff1a;134.加油站 题目描述&#xff1a; 在一条环路上有 n 个加油站&#xff0c;其中第 i 个加…

如何设置 Visual Studio Code 的滚轮缩放功能

Visual Studio Code (VSCode) 是一个强大的代码编辑器&#xff0c;提供了许多便捷的功能来提高开发效率。其中之一就是通过滚轮缩放字体大小。以下是详细的设置步骤&#xff1a; 步骤 1&#xff1a;打开设置页面 首先&#xff0c;启动 Visual Studio Code。在左上角点击 “文…

【网红时代】揭秘网红IP分析与打造,专业自媒体运营攻略

在这个互联网高速发展的时代&#xff0c;网红IP和自媒体的影响力日益凸显&#xff0c;成为品牌传播和市场营销的重要力量。如何分析和打造网红IP&#xff0c;进行专业的自媒体运营&#xff0c;成为许多企业和个人关注的焦点。今天&#xff0c;让我们一起探索网红IP的奥秘&#…

2024高端网站制作公司推荐TOP3

2024这个数字化高度发达的时间段&#xff0c;一个专业、高端的网站不仅是企业形象的展示窗口&#xff0c;更是连接用户与品牌的重要桥梁。 随着技术的不断进步和设计理念的不断创新&#xff0c;许多高端网站制作公司凭借其卓越的技术实力、创新的设计理念和丰富的项目经验&…

逻辑判断1-逻辑基础知识

目录 一、命题1.命题介绍2.复合命题1. 联合命题(且)2. 选言命题(或者、要么)3. 假言命题(如果、才、否则)3.模态命题(可能必然)4.直言命题(所有有些)5.充分必要条件二、推理方式一、命题 1.命题介绍 命题的四种形式和关系 命题传递规则 A→B,B→C,可联立,得出A→…