数据结构与算法(C)—散列表
数据结构与算法—散列表一、HASH数据结构定义二、HASH表创建三、HASH表插入四、HASH表查找五、HASH表删除六、HASH表打印七、测试程序本文变量命名前缀:全局变量:g_数组:a指针:p结构体:stunsigned int:ui本文代码可以到Github下载:https://github.com/liyuewu-github/DataStructure一、HASH数据结构定义需要定义HA
·
本文变量命名前缀:
- 全局变量:g_
- 数组:a
- 指针:p
- 结构体:st
- unsigned int:ui
本文代码可以到Github下载:https://github.com/liyuewu-github/DataStructure
一、HASH数据结构定义
需要定义HASH冲突域。HASH TABLE中增加HASH算法和排序算法,增强HASA TABLE可用性。
/* HASH冲突域链表节点 */
typedef struct tagHASH_LIST
{
unsigned int uiValue;
struct tagHASH_LIST *pHashList;
}HASH_LIST_S;
/* HASH表 */
typedef struct tagHASH_TABLE
{
unsigned int uiTableSize; /* HASH表大小 */
unsigned int (*pFunHash)(const void *); /* HASH算法 */
unsigned int (*pFunCmp)(unsigned int uiKey, unsigned int uiOldKey); /* HASH冲突域值比较 */
HASH_LIST_S **ppHashList; /* HASH数组链表 */
}HASH_TABLE_S;
二、HASH表创建
HASH表创建,指定HASA表长度。
/* HASH表创建 */
HASH_TABLE_S * HASH_Create(
IN unsigned int uiTableSize,
IN unsigned int (*pFunHash)(const void *),
IN unsigned int (*pFunCmp)(unsigned int uiKey, unsigned int uiOldKey))
{
HASH_TABLE_S *pstHashTable;
unsigned int i;
pstHashTable = malloc(sizeof(HASH_TABLE_S));
if (NULL == pstHashTable)
{
return NULL;
}
pstHashTable->ppHashList = malloc(sizeof(HASH_LIST_S) * uiTableSize);
if (NULL == pstHashTable->ppHashList)
{
free(pstHashTable);
return NULL;
}
memset(pstHashTable->ppHashList, 0, sizeof(HASH_LIST_S) * uiTableSize);
pstHashTable->uiTableSize = uiTableSize;
pstHashTable->pFunHash = pFunHash;
pstHashTable->pFunCmp = pFunCmp;
return pstHashTable;
}
三、HASH表插入
HASH表插入使用HASH算法找到index,再根据比较算法找到插入的位置。实现了HASH冲突域有序排列。
/* HASH表插入 */
unsigned int HASH_Insert( IN HASH_TABLE_S *pstHashTable, IN unsigned int uiKey)
{
HASH_LIST_S *pstHashFind;
HASH_LIST_S *pstNewHashNode;
HASH_LIST_S *pstHashCmp;
unsigned int uiHashIndex;
pstHashFind = HASH_Find(pstHashTable, uiKey);
if (NULL == pstHashFind)
{
pstNewHashNode = malloc(sizeof(HASH_LIST_S));
if (NULL == pstNewHashNode)
{
return HASH_NOMEM;
}
uiHashIndex = pstHashTable->pFunHash((void *)&uiKey);
pstNewHashNode->uiValue = uiKey;
pstHashCmp = pstHashTable->ppHashList[uiHashIndex];
while(pstHashCmp)
{
if (pstHashTable->pFunCmp(uiKey, pstHashCmp->uiValue ))
{
break;
}
pstHashCmp = pstHashCmp->pHashList;
}
if (NULL == pstHashCmp) /* 当前节点为冲突域中的最大值或者最小值 */
{
pstNewHashNode->pHashList = pstHashTable->ppHashList[uiHashIndex];
pstHashTable->ppHashList[uiHashIndex] = pstNewHashNode;
}
else /* 当前节点为冲突域中的中间值,插入pstHashCmp之后 */
{
pstNewHashNode->pHashList = pstHashCmp->pHashList;
pstHashCmp->pHashList = pstNewHashNode;
}
#ifdef HASH_TRACE
printf("Key %d index %d head %p node %p nextnode %p\n",uiKey, uiHashIndex,
pstHashTable->ppHashList[uiHashIndex],pstNewHashNode, pstNewHashNode->pHashList);
#endif
}
#ifdef HASH_TRACE
else
{
printf("The Key %d is repect\n",uiKey);
}
#endif
return HASH_OK;
}
四、HASH表查找
HASH查找需要遍历冲突域查找。这是一般的查找方法,对于实现了冲突域排序的HASH表,可以使用二分法查找。
/* HASH表查找 */
HASH_LIST_S *HASH_Find( IN HASH_TABLE_S *pstHashTable, IN unsigned int uiKey)
{
HASH_LIST_S *pstHashFind;
unsigned int uiHashIndex;
uiHashIndex = pstHashTable->pFunHash((void *)&uiKey);
pstHashFind = pstHashTable->ppHashList[uiHashIndex];
while(pstHashFind)
{
if(pstHashFind->uiValue == uiKey)
{
break;
}
pstHashFind = pstHashFind->pHashList;
}
return pstHashFind;
}
五、HASH表删除
/* HASH表删除 */
void HASH_Destroy(IN HASH_TABLE_S * pstHashTable)
{
HASH_LIST_S *pstHashScan;
unsigned int uiHashIndex;
for (uiHashIndex = 0; uiHashIndex < pstHashTable->uiTableSize; uiHashIndex++)
{
pstHashScan = pstHashTable->ppHashList[uiHashIndex];
while(pstHashScan)
{
free(pstHashScan);
pstHashScan = pstHashScan->pHashList;
}
}
free(pstHashTable->ppHashList);
free(pstHashTable);
return;
}
六、HASH表打印
/* HASH表打印 */
unsigned int HASH_Dump( IN HASH_TABLE_S *pstHashTable )
{
HASH_LIST_S *pstHashScan;
unsigned int uiHashIndex;
char * pcBuf;
unsigned int uiLen = 0;
pcBuf = (char * )malloc(HASH_BUFLEN);
if (NULL == pcBuf)
{
return HASH_NOMEM;
}
for (uiHashIndex = 0; uiHashIndex < pstHashTable->uiTableSize; uiHashIndex++)
{
uiLen += snprintf((pcBuf+uiLen), (HASH_BUFLEN-uiLen), "----------------HASH INDEX %u----------------\n", uiHashIndex);
pstHashScan = pstHashTable->ppHashList[uiHashIndex];
while(pstHashScan)
{
uiLen += snprintf((pcBuf+uiLen), (HASH_BUFLEN-uiLen), "node %p value %u\n", pstHashScan, pstHashScan->uiValue);
pstHashScan = pstHashScan->pHashList;
}
}
printf("%s", pcBuf);
free(pcBuf);
}
七、测试程序
100个数字0-99, 放到hash地址为0-19的hash表中, hash函数为key/5。将冲突值按大小顺序排列放入冲突域链表。
#define __TEST_PROCESS__
#define HASHTEST_MOD 5
#define HASHTEST_SIZE 20
unsigned int HASH(const void * pKey)
{
return (*(unsigned int *)pKey/HASHTEST_MOD);
}
unsigned int Cmp(unsigned int uiKey, unsigned int uiOldKey)
{
return (uiKey < uiOldKey ? 1 : 0);
}
void main()
{
HASH_TABLE_S * pstHashTest;
int i;
pstHashTest = HASH_Create(HASHTEST_SIZE, HASH,Cmp);
if (NULL == pstHashTest)
{
return;
}
for (i=0;i<100;i++)
HASH_Insert(pstHashTest, i);
HASH_Insert(pstHashTest, 17);
HASH_Insert(pstHashTest, 15);
HASH_Insert(pstHashTest, 16);
HASH_Dump(pstHashTest);
HASH_Destroy(pstHashTest);
return;
}
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献1条内容
所有评论(0)