哈希表

哈希表是一个用于快速查找键值的数据结构序列,本文的哈希表的实现用于构造字符串键和字符串值的哈希序列。主要应用于对象的属性集合的存取。
哈希表的结构有主散列和子序列构成,主散列是一线性数组,数组的大小为size,是一个素数,也是哈希函数的模基,数组序号[0...size]即哈希函数的值域,数组存储的是根连接件,由他维护着相同的哈希值(哈希函数值相同)的节点链表。子序列是存储节点的有序序列,是按各节点关键码升序排列的。哈希值和关键码都是由键值通过不同的函数生成的整型值。
查找的路径为,根据键值的哈希函数值在主散列中定位取得根连接件,然后在此子序列中根据键值的关键码筛选,最终通过键值的比较来定位到节点。
       以下为哈希表的定义和实现:
 
 
  /*************************************************************
       EasySoft xdl v3.0
 
       (c) 2003-2006 EasySoft Corporation. All Rights Reserved.
 
       @doc xdl.rtf: hash table
 
       @module       hashtable.h | hash table interface file
 
       @devnote PowerSuite 2003.01 - 2006.12
*************************************************************/
 
#ifndef _HASHTABLE_H
#define _HASHTABLE_H
 
#include "xdl/link.h"
#include "xdl/xdldef.h"
 
#ifdef __cplusplus
extern "C" {
#endif
 
/*define enum hash entity callback function */
typedef int (*EnumHashEntityPtr)(LINKPTR ent,voidpv);
/*
功能:枚举哈希表的键集的回调函数
参数:ent为本次枚举的键,pv回传的参数
返回:零值继续枚举,非零值终止枚举
*/
 
XDL_API LINKPTR CreateHashTable(int nSize);
/*
功能:创建哈希文档
参数:表大小,可以为MIN_PRIM,MID_PRM,MAX_PRIM
返回:哈希表文档连接件指针
*/
 
XDL_API void DestroyHashTable(LINKPTR ptr);
/*
功能:销毁哈希文档
参数:哈希表文档连接件指针
返回:无
*/
 
XDL_API void CopyHashTable(LINKPTR ptrDest,LINKPTR ptrSrc);
/*
功能:拷贝哈希文档
参数:ptrDest为目的哈希文档指针,ptrSrc为源哈希文档指针
返回:无
*/
 
XDL_API void ClearHashTable(LINKPTR ptr);
/*
功能:清除哈希文档键值集合
参数:哈希表文档连接件指针
返回:无
*/
 
XDL_API LINKPTR       AddHashEntity(LINKPTR ptr,const TCHARszKey,int keylen,const TCHARszVal,int vallen);
/*
功能:添加一个键集到哈希文档
参数:ptr为哈希表文档连接件指针,szKey为键名,keylen为键长度,szVal为键值,vallen为值长度
返回:键连接件指针,不存在的键名则添加新键,已存在的键名,键值将被覆盖
*/
 
XDL_API LINKPTR       GetHashEntity(LINKPTR ptr,const TCHARszKey,int keylen);
/*
功能:由键名检索键
参数:ptr为哈希表文档连接件指针,szKey为键名,keylen为键长度
返回:键的连接件指针,不存在则返回NULL
*/
 
XDL_API void DeleteHashEntity(LINKPTR elk);
/*
功能:删除键
参数:键的连接件指针
返回:无
*/
 
XDL_API const TCHARGetHashEntityKeyPtr(LINKPTR elk);
/*
功能:取键的名称指针
参数:键的连接件指针
返回:键名的指针
*/
 
XDL_API const TCHARGetHashEntityValPtr(LINKPTR elk);
/*
功能:取键值指针
参数:键的连接件指针
返回:键值的指针
*/
 
XDL_API int GetHashEntityKey(LINKPTR elk,TCHARbuf,int max);
/*
功能:拷贝键的名称
参数:elk为键的连接件指针,buf为缓冲区指针,max为缓冲区大小,不包括终结符
返回:实际拷贝的字节数
*/
 
XDL_API int GetHashEntityVal(LINKPTR elk,TCHARbuf,int max);
/*
功能:拷贝键值
参数:elk为键的连接件指针,buf为缓冲区指针,max为缓冲区大小,不包括终结符
返回:实际拷贝的字节数
*/
 
XDL_API void SetHashEntityData(LINKPTR elk,unsigned long data);
/*
功能:设置键的额外数据
参数:elk为键的连接件指针,data为额外数据
返回:无
*/
 
XDL_API unsigned long GetHashEntityData(LINKPTR elk);
/*
功能:取得键的额外数据
参数:elk为键的连接件指针
返回:额外数据
*/
 
XDL_API int       EnumHashEntity(LINKPTR ptr,EnumHashEntityPtr pf,voidpv);
/*
功能:枚举哈希文档的键
参数:ptr为哈希文档指针,pf为回调函数,pv为传入参数
返回:被枚举的键的计数
*/
 
XDL_API void HashTableParseOptions(LINKPTR ptr,const TCHARoptions,int len,TCHAR itemfeed,TCHAR linefeed);
/*
功能:从选项串中解析键与值集合
参数:ptr为哈希文档指针,options为选项串,格式如: 0~false;1~true;,len为选项串长度
itemfeed为名与值的隔离符号,如:~,linefeed为条目的隔离符号,如:;
返回:无
*/
 
XDL_API int HashTableFormatOptions(LINKPTR ptr,TCHARbuf,int max,TCHAR itemfeed,TCHAR linefeed);
/*
功能:将哈希文档的键值集合格式化成选项串
参数:ptr为哈希文档指针,buf为缓冲区指针,max为缓冲区长度,itemfeed为名与值的隔离符号,如:~,linefeed为条目的隔离符号,如:;
返回:无
*/
 
XDL_API int HashTableFormatOptionsSize(LINKPTR ptr,TCHAR itemfeed,TCHAR linefeed);
/*
功能:测试将哈希文档的键值集合格式化成选项串所需要的缓冲区大小,不包括终结符
参数:ptr为哈希文档指针,itemfeed为名与值的隔离符号,如:~,linefeed为条目的隔离符号,如:;
返回:无
*/
 
#ifdef __cplusplus
}
#endif
 
#endif 
/*_HASHTABLE_H*/
 
/*************************************************************
       EasySoft xdl v3.0
 
       (c) 2003-2006 EasySoft Corporation. All Rights Reserved.
 
       @doc xdl.rtf: hash table
 
       @module       hashtable.c | hash table implement file
 
       @devnote PowerSuite 2003.01 - 2006.12
*************************************************************/
 
/************************************************************
*************************************************************/
 
#include "xdl/hashtable.h"
#include "xdl/xdlutil.h"
 
typedef struct _HashEntity{
       
LINK lk;               /* entity self link component*/
       
TCHARszKey;            /* entity key, can not be null*/
       
TCHARszVal;             /* entity value*/
       
unsigned short code/* entity key code*/
       
unsigned long data;       /* entiry data for XdlFree use*/
}HashEntity;
 
typedef struct _HashTable{
       
LINK lk;               /* hash table self link component*/
       
LINKPTR pp;                 /* hash table master root link ptr array*/
       
int size;                 /* root link ptr array size, is prim value*/
}HashTable;
 
/* restore hash table struct ptr from link ptr*/
#define HashTableFromLink(p) ((HashTable*)((unsigned int)- (unsigned int)&(((HashTable*)0)->lk))) 
/* restore hash entity struct ptr from link ptr*/
#define HashEntityFromLink(p) ((HashEntity*)((unsigned int)- (unsigned int)&(((HashEntity*)0)->lk))) 
 
static int HashCode(const TCHARszKey,int keylen,int nPrim)
{
       
unsigned int sum;
       
int i;
 
       
assert(szKey);
       
assert(nPrim 0);
 
       
if(keylen == -1)
              
keylen _tcslen(szKey);
 
       
sum 0;
       
for(i=0;i<keylen;i++)
       {
              
sum += (unsigned int)(szKey[i]);
       }
       
return sum nPrim;
}
 
static unsigned short KeyCode(const TCHARszKey,int keylen)
{
       
unsigned short code;
       
int i;
 
       
assert(szKey);
 
       
if(keylen == -1)
              
keylen _tcslen(szKey);
 
       
code 0;
       
for(i=0;i<keylen;i++)
       {
              
code += (unsigned short)(szKey[i]);
              
code code << 1;
       }
       
return code ;
}
 
void _InsertEntity(LINKPTR root,LINKPTR ptrEntity)
{
       
HashEntitypnew;
       
HashEntityphe;
       
LINKPTR plk;
       
       
assert(root && root->tag == lkRoot);
       
assert(ptrEntity && ptrEntity->tag == lkHashEntity);
       
       
pnew HashEntityFromLink(ptrEntity);
       
plk GetFirstLink(root);
       
while(plk)
       {
              
phe HashEntityFromLink(plk);
              
if(phe->code pnew->code)
                     
break;/*find the prev link*/
              
              
plk GetNextLink(plk);
       }
       
       
if(plk == NULL)
       {
              
InsertLink(root,LINK_LAST,ptrEntity);
       }
else
       
{
              
InsertLinkBefore(root,plk,ptrEntity);
       }
}
 
LINKPTR CreateHashTable(int nSize)
{
       
HashTablepht;
       
int i;
       
       
assert(nSize 0);
       
pht = (HashTable*)XdlAlloc(1,sizeof(HashTable));
       
pht->lk.tag lkHashTable;
       
pht->size nSize;
       
pht->pp = (LINKPTR)XdlAlloc(nSize,sizeof(LINK));
       
for(0;i<pht->size;i++)
              
InitRootLink(pht->pp i);       /*initialize each master root link ptr*/
 
       
return &(pht->lk);
}
 
void DestroyHashTable(LINKPTR ptr)
{
       
HashTablepht;
 
       
assert(ptr);
       
assert(ptr->tag == lkHashTable);
 
       
pht HashTableFromLink(ptr);
       
ClearHashTable(ptr);       /*XdlFree all hash eitity*/
 
       
XdlFree(pht->pp);
       
XdlFree(pht);
}
 
void CopyHashTable(LINKPTR ptrDest,LINKPTR ptrSrc)
{
       
HashTablepht;
       
HashEntityphe;
       
LINKPTR plk;
       
int i;
       
       
assert(ptrDest && ptrDest->tag == lkHashTable);
       
assert(ptrSrc && ptrSrc->tag == lkHashTable);
 
       
pht HashTableFromLink(ptrSrc);
       
for(i=0;i<pht->size;i++)
       {
              
plk GetFirstLink(&((pht->pp)[i]));
              
while(plk != NULL)
              {
                     
phe HashEntityFromLink(plk);
 
                     
AddHashEntity(ptrDest,phe->szKey,-1,phe->szVal,-1);
 
                     
plk GetNextLink(plk);
              }
       }
}
 
void ClearHashTable(LINKPTR ptr)
{
       
HashTablepht;
       
HashEntityphe;
       
LINKPTR plk,pre;
       
int i;
 
       
assert(ptr);
       
assert(ptr->tag == lkHashTable);
 
       
pht HashTableFromLink(ptr);
 
       
for(i=0;i<pht->size;i++)
       {
              
plk GetFirstLink(&(pht->pp[i]));
              
while(plk)
              {
                     
pre plk;
                     
plk GetNextLink(plk);
                     
                     
phe HashEntityFromLink(pre);
                     
XdlFree(phe->szKey);
                     
if(phe->szVal)
                            
XdlFree(phe->szVal);
                     
XdlFree(phe);
              }
       }
 
       
for(0;i<pht->size;i++)
              
InitRootLink(pht->pp i);       /*set each master root link ptr to initialized state*/
}
 
LINKPTR       AddHashEntity(LINKPTR ptr,const TCHARszKey,int keylen,const TCHARszVal,int vallen)
{
       
HashTablepht;
       
HashEntityphe;
       
LINKPTR plk;
       
int nIndex;
 
       
assert(ptr);
       
assert(ptr->tag == lkHashTable);
 
       
if(IsNullStr(szKey) || keylen == 0)
              
return NULL;
 
       
pht HashTableFromLink(ptr);
       
/*first to find entity with the key*/
       
plk GetHashEntity(ptr,szKey,keylen);
       
if(plk != NULL)           /*if exist then to replace the entiry value*/
       
{
              
phe HashEntityFromLink(plk);
              
              
if(phe->szVal != NULL)
              {
                     
XdlFree(phe->szVal);
                     
phe->szVal NULL;
              }
              
if(!IsNullStr(szVal) && vallen)
              {
                     
if(vallen == -1)
                            
vallen _tcslen(szVal);
                     
phe->szVal = (TCHAR*)XdlAlloc(vallen 1,sizeof(TCHAR));
                     
_tcsncpy(phe->szVal,szVal,vallen);
              }
       }
else       /*if not exist then to add new entity with key and value*/
       
{     
              
phe = (HashEntity*)XdlAlloc(1,sizeof(HashEntity));
              
phe->lk.tag lkHashEntity;
              
              
if(keylen == -1)
                     
keylen _tcslen(szKey);
              
              
phe->szKey = (TCHAR*)XdlAlloc(keylen 1,sizeof(TCHAR));
              
_tcsncpy(phe->szKey,szKey,keylen);
              
phe->code KeyCode(szKey,keylen);
              
              
if(!IsNullStr(szVal) && vallen)
              {
                     
if(vallen == -1)
                            
vallen _tcslen(szVal);
                     
phe->szVal = (TCHAR*)XdlAlloc(vallen 1,sizeof(TCHAR));
                     
_tcsncpy(phe->szVal,szVal,vallen);
              }
              
              
nIndex HashCode(phe->szKey,keylen,pht->size);
              
plk = &((pht->pp)[nIndex]);
              
              
/*insert entity to list by key's asc order*/
              
_InsertEntity(plk,&phe->lk);
       }
 
       
return &(phe->lk);
}
 
LINKPTR       GetHashEntity(LINKPTR ptr,const TCHARszKey,int keylen)
{
       
int nIndex;
       
unsigned short code;
       
HashEntityphe;
       
HashTablepht;
       
LINKPTR plk;
 
       
assert(ptr);
       
assert(ptr->tag == lkHashTable);
 
       
if(IsNullStr(szKey) || keylen == 0)
              
return NULL;
 
       
pht HashTableFromLink(ptr);
 
       
if(keylen == -1)
              
keylen _tcslen(szKey);
 
       
/*first to calc master root link ptr array position by the key's hash code */
       
nIndex HashCode(szKey,keylen,pht->size);
       
code KeyCode(szKey,keylen);
       
/*then to compare the entity key in the ordered list*/
       
plk GetFirstLink(&((pht->pp)[nIndex]));
       
while(plk != NULL)
       {
              
phe HashEntityFromLink(plk);
              
if(phe->code == code)
              {
                     
if(== _tcsncmp(phe->szKey,szKey,keylen))
                     {
                            
if((int)_tcslen(phe->szKey) == keylen)
                                   
return plk;
                     }
              }
else if(phe->code code)
                     
return NULL;
       
              
plk GetNextLink(plk);
       }
 
       
return NULL;
}
 
void DeleteHashEntity(LINKPTR elk)
{
       
HashEntityphe;
 
       
assert(elk);
       
assert(elk->tag == lkHashEntity);
 
       
phe HashEntityFromLink(elk);
       
/*delete link ptr from list*/
       
DeleteLink(GetRootLink(elk),elk);
 
       
XdlFree(phe->szKey);
       
if(phe->szVal)
              
XdlFree(phe->szVal);
       
XdlFree(phe);
}
 
const TCHARGetHashEntityKeyPtr(LINKPTR elk)
{
       
HashEntityphe;
 
       
assert(elk);
       
assert(elk->tag == lkHashEntity);
       
phe HashEntityFromLink(elk);
       
return phe->szKey;
}
 
const TCHARGetHashEntityValPtr(LINKPTR elk)
{
       
HashEntityphe;
 
       
assert(elk);
       
assert(elk->tag == lkHashEntity);
       
phe HashEntityFromLink(elk);
       
return phe->szVal;
}
 
int GetHashEntityKey(LINKPTR elk,TCHARbuf,int max)
{
       
HashEntityphe;
       
int len;
 
       
assert(elk);
       
assert(elk->tag == lkHashEntity);
       
assert(buf && max >= 0);
       
phe HashEntityFromLink(elk);
       
len _tcslen(phe->szKey);
       
len = (len max)? len max;
       
_tcsncpy(buf,phe->szKey,len);
       
buf[len] = _T('/0');
 
       
return len;
}
 
int GetHashEntityVal(LINKPTR elk,TCHARbuf,int max)
{
       
HashEntityphe;
       
int len;
 
       
assert(elk);
       
assert(elk->tag == lkHashEntity);
       
assert(buf && max >= 0);
       
phe HashEntityFromLink(elk);
       
if(phe->szVal == NULL)
       {
              
buf[0] = _T('/0');
              
return 0;
       }
else
       
{
              
len _tcslen(phe->szVal);
              
len = (len max)? len max;
              
_tcsncpy(buf,phe->szVal,len);
             
buf[len] = _T('/0');
              
return len;
       }
}
 
void       SetHashEntityData(LINKPTR elk,unsigned long data)
{
       
HashEntityphe;
 
       
assert(elk);
       
assert(elk->tag == lkHashEntity);
 
       
phe HashEntityFromLink(elk);
       
phe->data data;
}
 
unsigned long GetHashEntityData(LINKPTR elk)
{
       
HashEntityphe;
 
       
assert(elk);
       
assert(elk->tag == lkHashEntity);
 
       
phe HashEntityFromLink(elk);
       
return phe->data;
}
 
int EnumHashEntity(LINKPTR ptr,EnumHashEntityPtr pf,voidpv)
{
       
HashTablepht;
       
HashEntityphe;
       
LINKPTR plk;
       
int i,count;
       
       
assert(ptr);
       
assert(ptr->tag == lkHashTable);
 
       
pht HashTableFromLink(ptr);
       
count 0;
       
for(i=0;i<pht->size;i++)
       {
              
plk GetFirstLink(&((pht->pp)[i]));
              
while(plk != NULL)
              {
                     
phe HashEntityFromLink(plk);
                     
count ++;
 
                     
if(pf == NULL)
                     {
                            
plk GetNextLink(plk);
                            
continue;
                     }
                     
/*if callback function return none zero value then to break enum*/
                     
if((*pf)(plk,pv))
                            
return count;
 
                     
plk GetNextLink(plk);
              }
       }
       
return count;
}
 
XDL_API void HashTableParseOptions(LINKPTR ptr,const TCHARoptions,int lenTCHAR itemfeed,TCHAR linefeed)
{
       
TCHARtoken;
       
TCHAR *key,*val;
       
int keylen,vallen;
 
       
assert(ptr && ptr->tag == lkHashTable);
 
       
ClearHashTable(ptr);
 
       
if(options == NULL || len == 0)
              
return;
 
       
if(len == -1)
              
len _tcslen(options);
 
       
token = (TCHAR*)options;
       
while(token != options len)
       {
              
key token;
              
while(*token != itemfeed && *token != _T('/0'))
                     
token ++;
              
keylen token key;
 
              
if(token == _T('/0'))
                     
break;
 
              
token ++; /*skip item feed*/
              
              
val token;
              
while(*token != linefeed && *token != _T('/0'))
                     
token ++;
              
vallen token val;
 
              
AddHashEntity(ptr,key,keylen,val,vallen);
 
              
if(*token == _T('/0'))
                     
break;
 
              
token ++; /*skip line feed*/
       
}
}
 
int HashTableFormatOptions(LINKPTR ptr,TCHARbuf,int max,TCHAR itemfeed,TCHAR linefeed)
{
       
HashTablepht;
       
HashEntityphe;
       
LINKPTR plk;
       
int i,total,len;
       
       
assert(ptr);
       
assert(ptr->tag == lkHashTable);
 
       
pht HashTableFromLink(ptr);
       
total 0;
 
       
for(i=0;i<pht->size;i++)
       {
              
plk GetFirstLink(&((pht->pp)[i]));
              
while(plk != NULL)
              {
                     
phe HashEntityFromLink(plk);
 
                     
len _tcslen(phe->szKey) + ((phe->szVal)? _tcslen(phe->szVal) : 0) + 2/*include itemfeed and linefeed*/
                     
if(total len max)
                            
return -1;
                     
if(buf)
                            
_stprintf(buf total,_T("%s%c%s%c"),phe->szKey,itemfeed,((phe->szVal)? phe->szVal _T("")),linefeed);
                     
total += len;
 
                     
plk GetNextLink(plk);
              }
       }
       
return total;
}
 
int HashTableFormatOptionsSize(LINKPTR ptr,TCHAR itemfeed,TCHAR linefeed)
{
       
return HashTableFormatOptions(ptr,NULL,MAX_INT,itemfeed,linefeed);
}
collected by barenx
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值