数据结构——哈希表

哈希表(Hash table,也叫散列表),是根据key而直接进行访问的数据结构。也就是说,它通过把key映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数

叫做散列函数,存放记录的数组叫做散列表。

  哈希表的做法其实很简单,就是把key通过一个固定的算法函数即所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的标,

将value存储在以该数字为下标的数组空间里。而当使用哈希表进行查询的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间获取value,如此一来,

就可以充分利用到数组的定位性能进行数据位。

Hash主要用于信息安全领域中加密算法,它把一些不同长度的信息转化成杂乱的128位的编码,这些编码值叫做HASH值. 也可以说,Hash就是找到一种数据内容和数据存

放地址之间的映射关系。

  数组的特点是:寻址容易,插入和删除困难;而链表的特点是:寻址困难,插入和删除容易。那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据

结构?答案是肯定的,这就是我们要提起的哈希表,哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法——拉链法,我们可以理解为“链表的数组”,如图:


hash.h

#ifndef _HASH_H_
#define _HASH_H_

#define HASH_SIZE 26
#define NAME_PWD_SIZE 20

enum HASH_OP
{
	HASH_ERR = -1,
	HASH_OK
};

typedef struct UserInfo
{
	char strName[NAME_PWD_SIZE];
	char strPwd[NAME_PWD_SIZE];
} data_t;

typedef struct HNode
{
	data_t data;
	struct HNode *pNext;
}HNODE;

typedef struct Hash
{
	struct HNode *table[HASH_SIZE];
}HASH;

HASH *CreateHash();
void DestroyHash(HASH *pHash);
int InsertItem(HASH *pHash, data_t tData);
int DeleteItem(HASH *pHash, data_t tDel);
void ShowHash(HASH *pHash);

#endif //_HASH_H_


hash.c

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

HASH *CreateHash()
{
	HASH *pHash = NULL;
	pHash = (HASH *) malloc(sizeof(HASH));
    if(NULL == pHash)
	{
		return pHash;
	}
	memset(pHash,0,sizeof(HASH));
	return pHash;
}
	

void DestroyHash(HASH *pHash)
{
	if (NULL == pHash)
	{
		return;
	}
	int i = 0;
	for(; i < HASH_SIZE; i++)
	{
		if (NULL == pHash->table[i])
		{
			continue;
		}
		HNODE *pTmp = pHash->table[i];
		HNODE *pTmp1 = NULL;
		while(NULL != pTmp)
		{
			pTmp1=pTmp->pNext;
			free(pTmp);
			pTmp = pTmp1;
		}
	}
	free(pHash);
	pHash = NULL;
}

int InsertItem(HASH *pHash, data_t tData)
{
	if (NULL == pHash || 0 == strlen(tData.strName) || 0 == strlen(tData.strPwd))
	{
		return HASH_ERR;
	}
	//create hash node
	HNODE *pNode = (HNODE *) malloc (sizeof(HNODE));
	if (NULL == pNode)
	{
		return HASH_ERR;
	}
	memset(pNode, 0, sizeof(HNODE));
	pNode->data = tData;
	//insert
	int iIndex = tData.strName[0] - 'a';
	pNode->pNext = pHash->table[iIndex];
	pHash->table[iIndex] = pNode;
	return HASH_OK;
}

int DeleteItem(HASH *pHash, data_t tDel)
{
	if (NULL == pHash || 0 == strlen(tDel.strName) || 0 == strlen(tDel.strPwd))
	{
		return HASH_ERR;
	}
	//delete item
	int iIndex = tDel.strName[0] - 'a';
	HNODE *pTmp = pHash->table[iIndex];
	if (NULL == pTmp)
	{
		return HASH_ERR;
	}
	if (0 == strcmp(tDel.strName, pTmp->data.strName)
		&& 0 == strcmp(tDel.strPwd, pTmp->data.strPwd))
	{
		pHash->table[iIndex] = pTmp->pNext;
		free(pTmp);
		pTmp = NULL;
		return HASH_OK;
	}
	//else
	{
		HNODE *pDel = NULL;
		while(NULL != pTmp->pNext)
		{
			pDel = pTmp->pNext;
			if (0 == strcmp(tDel.strName, pDel->data.strName)
				&& 0 == strcmp(tDel.strPwd, pDel->data.strPwd))
			{
				pTmp->pNext = pDel->pNext;
				free(pDel);
				pDel = NULL;
				return HASH_OK;
			}
			pTmp = pDel;
		}
		return HASH_ERR;
	}
	
}

void ShowHash(HASH *pHash)
{
	if (NULL == pHash)
	{
		return;
	}
	int i = 0;
	for (; i < HASH_SIZE; i++)
	{
		if (NULL == pHash->table[i])
		{
			continue;
		}
		HNODE *pTmp = pHash->table[i];
		while(NULL != pTmp)
		{
			printf("name : %s , pwd : %s\r\n", pTmp->data.strName
					, pTmp->data.strPwd);
			pTmp = pTmp->pNext;
		}
	}
}

main.c

#include <stdio.h>
#include <string.h>
#include "hash.h"

#define BUF_SIZE 100

enum MAIN_OP
{
	MAIN_ERR = -1,
	MAIN_OK
};

int PacketData(char *buf, data_t *pData)
{
	if (NULL == buf || NULL == pData)
	{
		return MAIN_ERR;
	}
	int i = 0;
	while(*buf != ' ')
	{
		pData->strName[i] = *buf;
		buf++;
		i++;
	}
	buf++;
	strcpy(pData->strPwd, buf);
	return MAIN_OK;
}

int main()
{
	HASH *pHash = CreateHash();
	if(NULL == pHash)
	{
		return -1;
	}
	printf("create ok\r\n");
	
	char buf[BUF_SIZE];
	data_t tData;
	while(1)
	{
		memset(buf, 0, BUF_SIZE);
		memset(&tData, 0, sizeof(data_t));
		gets(buf);
		if (0 == strncmp(buf, "insert", 6))
		{
			//printf("insert command\r\n");
			if (MAIN_OK != PacketData(buf+7, &tData))
			{
				continue;
			}
			//printf("%s : %s\r\n", tData.strName, tData.strPwd);
			if (HASH_OK != InsertItem(pHash, tData))
			{
				printf("insert error\r\n");
			}
		}
		else if (0 == strncmp(buf, "quit", 4))
		{
			break;
		}
		else if (0 == strncmp(buf, "show", 4))
		{
			ShowHash(pHash);
		}
		else if (0 == strncmp(buf, "delete", 6))
		{
			if (MAIN_OK != PacketData(buf+7, &tData))
			{
				continue;
			}
			if (HASH_OK != DeleteItem(pHash, tData))
			{
				printf("delete error\r\n");
			}
		}
	}
	DestroyHash(pHash);
	pHash = NULL;
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值