哈希表(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_
#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;
}