c语言实现hashtable,类似C++的map和iOS的NSDictionary

跟线性数组和链表不同,HashTable是快速查找的数据结构。本文中的HashTable使用链表处理数组。

该HashTable可以指定table的长度,提供了遍历的方法。包括table的长度的选择也比较讲究。

	cp_int32 nPrime[MAX_HASH_PRIME_ARRAY_NUM] = {
		17,
		37,
		79,
		163,
		331,
		673,
		1361
	};

就是说table的长度来取自上面这个数组。比如用户设定了200,那么table的长度就是331,找到第一次比输入值大的数值。可以注意到上面的都是素数。

下面是具体的代码贴出来,共大家参考。

代码中有个接口是查到多个key使用到了动态数组dyArray,参考上一篇点击打开链接

//
//  cpPlatform.h
//  dataStruct
//
//  Created by hherima on 14-7-29.
//  Copyright (c) 2014年 . All rights reserved.
//

#ifndef dataStruct_cpPlatform_h
#define dataStruct_cpPlatform_h

enum
{
    CP_FALSE  =   0,
    CP_TRUE    =  !CP_FALSE
};

#define  F_MALLOC_TYPE(s) (s*)f_malloc(sizeof(s))
#define  FREEFUN free
#define  MIN_PRE_ALLOCATE_SIZE 10  //The initial size of the dynamic array.
#define  MEMSETFUN      memset
#define  REALLOCFUN     realloc
#define  MALLOCFUN      malloc
#define  MEMCMPFUN      memcmp
#define  MEMCPYFUN      memcpy

typedef unsigned char cp_bool;
typedef signed int cp_int32;
typedef char cp_int8;
typedef unsigned int cp_uint32;

#endif

上面是数据类型的定义,为了跨平台使用

下面是hashtable的数据结构头文件

//
//  hashStruct.h
//  dataStruct
//
//  Created by hherima on 14-7-29.
//  Copyright (c) 2014年 . All rights reserved.
//

#ifndef dataStruct_hashStruct_h
#define dataStruct_hashStruct_h
#include <stdlib.h>
#include "cpPlatform.h"
#include "dyArray.h"

struct Node
{
    cp_int8* m_pKey; //the hash key.
    cp_int32 m_nKeyLength; // the length of the hash key in bytes.
    void* m_pVal;//hash_node value
    struct Node* m_pNext;
};//hash table,use link list to process conflict

struct HashTable
{
    cp_int32 m_nLength; //hash table's length.
    cp_int32 m_nEleNum; //hash table's element count.
    struct Node **m_ppHead;//the hash table's array to record all key's value.
};

cp_int32 GetHashFileNum(cp_int8* pKey, cp_int32 nKeyLength);

struct Node* HashFindOne(cp_int8* pKey,cp_int32 nKeyLength,struct HashTable *pTable);//search

cp_int32 HashFindMultkeyredund(cp_int8* pKey,cp_int32 nKeyLength,struct HashTable *pTable,struct DynamicArray *pdestArray);
void HashInsertOne(cp_int8* pKey,cp_int32 nKeyLength,void* pVal,struct HashTable *pTable);//insert
void HashInsertOneKeyredund(char* pKey,cp_int32 nKeyLength,void* pVal,struct HashTable *pTable);

void HashDelOne(struct HashTable * pTable,void (*pFreeFunc) (void *),cp_int8 *pKey,cp_int32 nKeyLength);

struct HashTable * HashTableCreate(cp_int32 nKeyNum);
struct Node* HashGetFirst(struct HashTable *pTable);
struct Node* HashGetNext(struct HashTable *pTable,cp_int8* pKey,cp_int32 nKeyLength);

cp_int32 HashGetLength(struct HashTable *pTable);
void HashTableVisit(struct HashTable * pTable,void (*pVisitFunc) (void *,void *),void *pAgent);
void HashTableReset(struct HashTable * pTable,void (*pFreeFunc) (void *));

void HashTableDestroy(struct HashTable * pTable,void (*pFreeFunc) (void *));

cp_int32 HashGetValue(cp_int8* pKey,cp_int32 nKeyLength,cp_int32 nTableLength);

#endif

源文件

//
//  hashStruct.c
//  dataStruct
//
//  Created by hherima on 14-7-29.
//  Copyright (c) 2014年 . All rights reserved.
//
#include "hashStruct.h"

#define MAX_HASH_PRIME_ARRAY_NUM    7
/**************************************************************************************************
 function name:
 HashGetValue
 description:
 the hash arithmetic to get the position of the certain key.
 parameter:
 pKey: the exclusive symbol which is related to a data block in hash table.
 nKeyLength: the key string's length.
 nTableLength: the hash table's length.
 return value:
 the position of the certain key.
 ***************************************************************************************************/

cp_int32 HashGetValue(cp_int8* pKey,cp_int32 nKeyLength,cp_int32 nTableLength)
{
	cp_uint32 h = 0;
	cp_uint32 g = 0;

	if(!pKey || nKeyLength<1 || nTableLength<1) //if the input parameter is invalid, return.
    {
        return -1;
    }
	while(nKeyLength--) // get each charactor and use it to compute hash value.
	{
		h = (h<<4) + *pKey++;
		g = h & 0xF0000000L;
		if(g)
		{
			h ^= g>>24;
		}
		h &= ~g;
	}
	return h % nTableLength;
}

/**************************************************************************************************
 function name:
 HashFindOne
 description:
 search the position's node of the certain key.
 parameter:
 pKey: the exclusive symbol which is related to a data block in hash table.
 nKeyLength: the key string's length.
 pTable: the hash table.
 return value:
 the node pointer or null.
 ***************************************************************************************************/

struct Node* HashFindOne(cp_int8* pKey,cp_int32 nKeyLength,struct HashTable *pTable)//search
{
    cp_int32 nPos = 0;
	struct Node* pCur = NULL;

    //if the input parameter is invalid, return.
	if(!pTable || !pKey || nKeyLength<1)
    {
        return NULL;
    }
    nPos = HashGetValue(pKey,nKeyLength,pTable->m_nLength);
    if(nPos>=0)
    	pCur = pTable->m_ppHead[nPos];
    //cur = table->head[hash_get_value(key,key_length,table->length)];
	while(pCur) // if has link list, visit all the list to find the right one.
	{
		if(pCur->m_nKeyLength == nKeyLength && MEMCMPFUN(pCur->m_pKey,pKey,nKeyLength) == 0)
		{
			return pCur;
		}
		pCur = pCur->m_pNext;
	}
	return NULL;
}

/**************************************************************************************************
 function name:
 HashFindMultkeyredund
 description:
 search the node of the certain key, there will be several one.
 parameter:
 pKey: the exclusive symbol which is related to several data block in hash table.
 nKeyLength: the key string's length.
 pTable: the hash table.
 pdestArray: the dynamic array which is used to save results and need be initilalized.
 return value:
 the node pointer or null.
 ***************************************************************************************************/

cp_int32 HashFindMultkeyredund(cp_int8* pKey,cp_int32 nKeyLength,struct HashTable *pTable,struct DynamicArray *pDestArray) //search ,the key is redundant.
{
	int nResNum = 0;
	struct Node* pCur = NULL;

    //if the input parameter is invalid, return.
	if(!pTable || !pKey || nKeyLength<1 || !pDestArray)
    {
        return -1;
    }
    pCur = pTable->m_ppHead[HashGetValue(pKey,nKeyLength,pTable->m_nLength)];
	while(pCur) //if has link list, visit all the list and find the right one.
	{
		if(pCur->m_nKeyLength == nKeyLength && MEMCMPFUN(pCur->m_pKey,pKey,nKeyLength) == 0)
		{
			DyArrayAppend(pDestArray, pCur->m_pVal); // put the right one to array.
			nResNum++;
			//return cur;
		}
		pCur = pCur->m_pNext;
	}
	return nResNum;
}

/**************************************************************************************************
 function name:
 hashExpand
 description:
 expand the array when it's too small.THIS FUNCTION CAN'T BE USED BECAUSE HASH VALUE IS
 CHANGED WHEN TABLE LENGTH CHANGED.
 parameter:
 pTable: the hash table.
 nNeed: the needed new size.
 return value:
 if succeed,return the true, else, return false.
 ***************************************************************************************************/

cp_bool HashExpand(struct HashTable * pTable, cp_int32 nNeed)
{
	cp_int32 i;
    struct Node ** pData = NULL;
    cp_int32 nAllocSize = 0;
	cp_int32 nPrime[MAX_HASH_PRIME_ARRAY_NUM] = {
		17,   //0
		37,   //1
		79,   //2

		163,  //3
		331,  //4
		673,  //5

		1361  //6
	};//The prime table used to be the length of hash table to decrease conflict.

    //if the input parameter is invalid, return.
	if(!pTable || nNeed<1)
    {
        return CP_FALSE;
    }
    //if need, expand to one and half times of original size.
	if(((pTable->m_nEleNum + nNeed) + ((pTable->m_nEleNum + nNeed)>>1) ) > pTable->m_nLength)
	{
		nAllocSize = pTable->m_nLength + (pTable->m_nLength>>1);
		for(i=0; i<MAX_HASH_PRIME_ARRAY_NUM; i++) //find the nearest one of prime array.
		{
			if(nPrime[i] > nAllocSize)
			{
				nAllocSize = nPrime[i];
				break;
			}
		}
        pData = (struct Node **)REALLOCFUN(pTable->m_ppHead, sizeof(struct Node *) * nAllocSize);
        if(pData != NULL)
        {
            // clear the expanded space.
            MEMSETFUN(pData+pTable->m_nLength,0,(nAllocSize-pTable->m_nLength)*sizeof(struct Node *));
            pTable->m_ppHead = pData;
            pTable->m_nLength = nAllocSize;
		}
	}
	return ((pTable->m_nEleNum + nNeed) + ((pTable->m_nEleNum + nNeed)>>1) <= pTable->m_nLength) ? CP_TRUE : CP_FALSE;
}

/**************************************************************************************************
 function name:
 HashInsertOne
 description:
 insert the node of the certain key.
 parameter:
 pKey: the exclusive symbol which is related to a data block in hash table.
 nKeyLength: the key string's length.
 pVal: the node pointer of the certain key.
 pTable: the hash table.
 return value:
 none.
 ***************************************************************************************************/

void HashInsertOne(cp_int8* pKey,cp_int32 nKeyLength,void* pVal,struct HashTable *pTable)//insert
{
	cp_int32 nPos = 0;
	struct Node** pNode = NULL;
	struct Node* pTmp = NULL;

    //if the input parameter is invalid, return.
    if(!pTable || !pKey || nKeyLength<1)
    {
        return ;
    }
    //comment it because when it expands, the same key's position changed and the original key position CAN'T be found.
	/*if((pTable->m_EleNum + 1) + ((pTable->m_EleNum + 1)>>1) > pTable->m_nLength)
     {
     HashExpand(pTable, 1);
     }*/
	//compute the hash position.
	pTable->m_nEleNum++;
	nPos = HashGetValue(pKey,nKeyLength,pTable->m_nLength);
	pNode = &pTable->m_ppHead[nPos];

    //if this key is NOT exist, insert it.
	if(HashFindOne(pKey,nKeyLength,pTable) == NULL)
	{
	    //malloc a new node and set the value.
		pTmp=(struct Node*)MALLOCFUN(sizeof(struct Node));
		MEMSETFUN(pTmp,0,sizeof(struct Node));
		pTmp->m_pKey = (char*)MALLOCFUN(nKeyLength+2);//for Unicode, two bytes zero is needed.
		MEMSETFUN(pTmp->m_pKey,0,nKeyLength+2);
		MEMCPYFUN(pTmp->m_pKey,pKey,nKeyLength);
		pTmp->m_nKeyLength = nKeyLength;
		pTmp->m_pVal = pVal;
		pTmp->m_pNext=NULL;
        //if there is a list, then insert to the tail.
		while(*pNode)
		{
			pNode = &((*pNode)->m_pNext);
		}
		*pNode = pTmp;
	}
}

/**************************************************************************************************
 function name:
 HashInsertOneKeyredund
 description:
 insert the node of the certain key.
 parameter:
 pKey: the symbol which is related to a data block in hash table.
 nKeyLength: the key string's length.
 pVal: the node pointer of the certain key.
 pTable: the hash table.
 return value:
 none.
 ***************************************************************************************************/

void HashInsertOneKeyredund(cp_int8* pKey,cp_int32 nKeyLength,void* pVal,struct HashTable *pTable) //insert,key is redundant.
{
	cp_int32 nPos = 0;
	struct Node** pNode = NULL;
	struct Node* pTmp = NULL;

    //if the input parameter is invalid, return.
    if(!pTable || !pKey || nKeyLength<1)
    {
        return ;
    }
    //comment it because when it expands, the same key's position changed and the original key position CAN'T be found.
	/*if((table->ele_num + 1) + ((table->ele_num + 1)>>1) > table->length)
     {
     hash_expand(table, 1);
     }*/
	//compute the hash position.
	pTable->m_nEleNum++;
	nPos= HashGetValue(pKey,nKeyLength,pTable->m_nLength);
	pNode = &pTable->m_ppHead[nPos];

    //compare with HashInsertOne, comment this line. if(hash_find_one(key,key_length,table) == NULL)
	{
	    //malloc a new node and set the value.
		pTmp=(struct Node*)MALLOCFUN(sizeof(struct Node));
		MEMSETFUN(pTmp,0,sizeof(struct Node));
		pTmp->m_pKey = (char*)MALLOCFUN(nKeyLength+2);//for Unicode, two bytes zero is needed.
		MEMSETFUN(pTmp->m_pKey,0,nKeyLength+2);
		MEMCPYFUN(pTmp->m_pKey,pKey,nKeyLength);
		pTmp->m_nKeyLength = nKeyLength;
		pTmp->m_pVal = pVal;
		pTmp->m_pNext=NULL;
        //if has a link list, then insert the new node to the tail.
		while(*pNode)
		{
			pNode = &((*pNode)->m_pNext);
		}
		*pNode = pTmp;
	}
}

/**************************************************************************************************
 function name:
 HashTableCreate
 description:
 create the hash table when the program starts.
 parameter:
 nKeyNum: the key count of the program's data.
 return value:
 the hash table.
 ***************************************************************************************************/

struct HashTable * HashTableCreate(cp_int32 nKeyNum)
{
	struct HashTable * pTable = NULL;
	cp_int32 i;
	cp_int32 nPrime[MAX_HASH_PRIME_ARRAY_NUM] = {
		17,   //0
		37,   //1
		79,   //2

		163,  //3
		331,  //4
		673,  //5

		1361  //6
	};//The prime table used to be the length of hash table to decrease conflict.

    //if the input parameter is invalid, return.
    if(nKeyNum < 1)
    {
        return NULL;
    }
	pTable = (struct HashTable *)MALLOCFUN(sizeof(struct HashTable));
	if(!pTable)
    {
		return NULL;
    }
	MEMSETFUN(pTable,0,sizeof(struct HashTable));
    //The default length is 1.5 times of key's number.
	pTable->m_nLength = nKeyNum + (nKeyNum<<1);
    //find the nearest size of prime array.
	for(i=0; i<MAX_HASH_PRIME_ARRAY_NUM; i++)
	{
		if(nPrime[i] > pTable->m_nLength)
		{
			pTable->m_nLength = nPrime[i];
			break;
		}
	}
	pTable->m_ppHead = (struct Node **) MALLOCFUN(sizeof(struct Node *)*pTable->m_nLength);
	if(!pTable->m_ppHead)
	{
		FREEFUN(pTable);
		return NULL;
	}
	MEMSETFUN(pTable->m_ppHead,0,sizeof(struct Node *)*pTable->m_nLength);
	return pTable;
}
/**************************************************************************************************
 function name:
 HashTableVisit
 description:
 visit all the elements of the hash table.
 parameter:
 pTable: the hash table.
 pVisitFunc: the visit function for each element of the hash table, the first parameter is hash's element,
 the second parameter is 'agent' which is to pass to caller.
 pAgent: used to pass to the call back funtion.
 return value:
 none
 ***************************************************************************************************/

void HashTableVisit(struct HashTable * pTable,void (*pVisitFunc) (void *,void *),void *pAgent)
{
	cp_int32 i;
	struct Node * pTmp = NULL;

    //if the input parameter is invalid, return.
    if(!pTable)
    {
        return ;
    }
    //visit each position if it's not null.
	for(i=0; i<pTable->m_nLength; i++)
	{
		if(pTable->m_ppHead[i] == NULL)
        {
            continue;
        }
		if(pTable->m_ppHead[i]->m_pKey)
		{
			if(pVisitFunc)
			{
				pVisitFunc(pTable->m_ppHead[i]->m_pVal,pAgent);
			}
			pTmp = pTable->m_ppHead[i]->m_pNext;
            //if has link list, then visit the whole list.
			while(pTmp)
			{
				if(pVisitFunc)
				{
					pVisitFunc(pTmp->m_pVal,pAgent);
				}
				pTmp = pTmp->m_pNext;
			}
		}
	}
	return ;
}

/**************************************************************************************************
 function name:
 HashGetFirst
 description:
 get the first element of the hash table.
 parameter:
 pTable: the hash table.
 return value:
 the first element
 ***************************************************************************************************/

struct Node* HashGetFirst(struct HashTable *pTable)
{
	cp_int32 i;

    //if the input parameter is invalid, return.
    if(!pTable)
    {
        return NULL;
    }
    //find the first not null element of head array.
	for(i=0; i<pTable->m_nLength; i++)
	{
		if(pTable->m_ppHead[i] == NULL)
        {
            continue;
        }
		if(pTable->m_ppHead[i]->m_pKey)
		{
			return pTable->m_ppHead[i];
		}
	}
	return NULL;
}

/**************************************************************************************************
 function name:
 HashGetNext
 description:
 get the next element of the current node which key is given.
 parameter:
 pTable: the hash table.
 pKey: the exclusive symbol which is related to a data block in hash table.
 nKeyLength: the key string's length.
 return value:
 the next element
 ***************************************************************************************************/

struct Node* HashGetNext(struct HashTable *pTable,cp_int8* pKey,cp_int32 nKeyLength)
{
    struct Node* pNext = NULL;
    struct Node* pCur = NULL;
    cp_int32 nPos;
    cp_int32 i;

    //if the input parameter is invalid, return.
    if(!pTable)
    {
        return NULL;
    }
    //get the position of the key.
    nPos = HashGetValue(pKey,nKeyLength,pTable->m_nLength);
    if(nPos == -1)
    {
        return NULL;
    }
    pCur = pTable->m_ppHead[nPos];
    if(!pCur)
    {
        return NULL;//the related node of the pKey is NOT exist, so return null.
    }
    //find the right one whose key is same with pKey.
    while(pCur)
    {
        if(pCur->m_nKeyLength == nKeyLength && MEMCMPFUN(pCur->m_pKey,pKey,nKeyLength) == 0)
        {
            break;
        }
        pCur = pCur->m_pNext;
    }
    //get the next pointer directly.
    if(pCur && pCur->m_pNext)
    {
        pNext = pCur->m_pNext;
    }
    else
    {
        //get the next not null one from the head array.
        nPos++;
        for(i=nPos; i<pTable->m_nLength; i++)
        {
            if(pTable->m_ppHead[i] == NULL)
            {
                continue;
            }
            if(pTable->m_ppHead[i]->m_pKey)
            {
                pNext = pTable->m_ppHead[i];
                break;
            }
        }
    }
    return pNext;
}

/**************************************************************************************************
 function name:
 HashTableReset
 description:
 clear the hash table.
 parameter:
 pTable: the hash table.
 pFreeFunc: the free function for hash data "val" which is given by caller.
 return value:
 none
 ***************************************************************************************************/

void HashTableReset(struct HashTable * pTable,void (*pFreeFunc) (void *))
{
	cp_int32 i;
	struct Node * pTmp = NULL;
	struct Node * pTmp1 = NULL;

    //if the input parameter is invalid, return.
    if(!pTable)
    {
        return;
    }
    //reset each element of the head array and free related memory.
	for(i=0; i<pTable->m_nLength; i++)
	{
		if(pTable->m_ppHead[i] == NULL)
        {
            continue;
        }
		if(pTable->m_ppHead[i]->m_pKey)
		{
			FREEFUN(pTable->m_ppHead[i]->m_pKey);
			if(pFreeFunc)
			{
				pFreeFunc(pTable->m_ppHead[i]->m_pVal);
			}
			pTmp = pTable->m_ppHead[i]->m_pNext;
			FREEFUN(pTable->m_ppHead[i]);
			pTable->m_ppHead[i] = NULL;
            //free all the link list.
			while(pTmp)
			{
				FREEFUN(pTmp->m_pKey);
				if(pFreeFunc)
				{
					pFreeFunc(pTmp->m_pVal);
				}
				pTmp1 = pTmp;
				pTmp = pTmp->m_pNext;
				FREEFUN(pTmp1);
			}
		}
	}
    //clear the table.
	MEMSETFUN(pTable->m_ppHead,0,sizeof(struct Node *)*pTable->m_nLength);
	pTable->m_nEleNum = 0;
	return ;
}

/**************************************************************************************************
 function name:
 HashTableDestroy
 description:
 destroy the hash table when the program exits.
 parameter:
 pTable: the hash table.
 pFreeFunc: the free function for hash data "val" which is given by caller.
 return value:
 none
 ***************************************************************************************************/

void HashTableDestroy(struct HashTable * pTable,void (*pFreeFunc) (void *))
{
	cp_int32 i;
	struct Node * pTmp = NULL;
	struct Node * pTmp1 = NULL;

    //if the input parameter is invalid, return.
    if(!pTable)
    {
        return;
    }
    //clear each element and free its memory.
	for(i=0; i<pTable->m_nLength; i++)
	{
		if(pTable->m_ppHead[i] == NULL)
        {
            continue;
        }
		if(pTable->m_ppHead[i]->m_pKey)
		{
			FREEFUN(pTable->m_ppHead[i]->m_pKey);
			if(pFreeFunc)
			{
				pFreeFunc(pTable->m_ppHead[i]->m_pVal);
			}
			pTmp = pTable->m_ppHead[i]->m_pNext;
			FREEFUN(pTable->m_ppHead[i]);
			pTable->m_ppHead[i] = NULL;
            //free the link list.
			while(pTmp)
			{
				FREEFUN(pTmp->m_pKey);
				if(pFreeFunc)
				{
					pFreeFunc(pTmp->m_pVal);
				}
				pTmp1 = pTmp;
				pTmp = pTmp->m_pNext;
				FREEFUN(pTmp1);
			}
		}
	}
    //free the table.
	FREEFUN(pTable->m_ppHead);
	pTable->m_ppHead = NULL;
	FREEFUN(pTable);
	return ;
}

/**************************************************************************************************
 function name:
 HashDelOne
 description:
 delete one node of hash table.
 parameter:
 pTable: the hash table.
 pFreeFunc: the free function for hash data "val" which is given by caller.
 pKey: the exclusive symbol which is related to a data block in hash table.
 nKeyLength: the key string's length.
 return value:
 none
 ***************************************************************************************************/

void HashDelOne(struct HashTable * pTable,void (*pFreeFunc) (void *),char *pKey,cp_int32 nKeyLength)
{
	cp_int32 nPos = 0;
	struct Node *pTmp = NULL;
	struct Node **pTmp1 = NULL;
	struct Node *pTmp2 = NULL;

    //if the input parameter is invalid, return.
    if(!pTable || !pKey || nKeyLength<1)
    {
        return;
    }
    //compute the hash position.
    nPos = HashGetValue(pKey,nKeyLength,pTable->m_nLength);
	if(!pTable->m_ppHead[nPos])
    {
        return;//the related node of the key is NOT exist, return.
    }
    //the first one is the right one.
	if(pTable->m_ppHead[nPos]->m_nKeyLength == nKeyLength && MEMCMPFUN(pTable->m_ppHead[nPos]->m_pKey,pKey,nKeyLength) == 0)
	{
		pTable->m_nEleNum--;
		FREEFUN(pTable->m_ppHead[nPos]->m_pKey);
		pTable->m_ppHead[nPos]->m_pKey = NULL;
		if(pFreeFunc)
			pFreeFunc(pTable->m_ppHead[nPos]->m_pVal);
		pTable->m_ppHead[nPos]->m_pVal = NULL;
		if(pTable->m_ppHead[nPos]->m_pNext)
		{
			pTmp = pTable->m_ppHead[nPos];
			pTable->m_ppHead[nPos] = pTable->m_ppHead[nPos]->m_pNext;
			FREEFUN(pTmp);
		}
		else
		{
			FREEFUN(pTable->m_ppHead[nPos]);
			pTable->m_ppHead[nPos] = NULL;
		}
	}
	else
	{
	    //find the right one in the link list.
		pTmp1 = &(pTable->m_ppHead[nPos]->m_pNext);
		while(*pTmp1)
		{
			if((*pTmp1)->m_nKeyLength == nKeyLength && MEMCMPFUN((*pTmp1)->m_pKey,pKey,nKeyLength) == 0)
			{
				//find it, free it and relink the link list.
				pTable->m_nEleNum--;
				FREEFUN((*pTmp1)->m_pKey);
				(*pTmp1)->m_pKey = NULL;
				if(pFreeFunc)
					pFreeFunc((*pTmp1)->m_pVal);
				(*pTmp1)->m_pVal = NULL;
				if((*pTmp1)->m_pNext)
				{
					pTmp2 = *pTmp1;
					*pTmp1 = (*pTmp1)->m_pNext;
					FREEFUN(pTmp2);
				}
				else
				{
					FREEFUN(*pTmp1);
					*pTmp1 = NULL;
				}
				break;
			}
			else
			{
				pTmp1 = &((*pTmp1)->m_pNext);
			}
		}
	}
	return ;
}

/**************************************************************************************************
 function name:
 HashGetLength
 description:
 get the total length of the hash table.
 parameter:
 pTable: the hash table.
 return value:
 none
 ***************************************************************************************************/

cp_int32 HashGetLength(struct HashTable *pTable)
{
    return pTable ? pTable->m_nEleNum : -1;
}

c语言实现hashtable,类似C++的map和iOS的NSDictionary

时间: 2024-10-05 23:22:42

c语言实现hashtable,类似C++的map和iOS的NSDictionary的相关文章

c语言实现hashtable,相似C++的map和iOS的NSDictionary

跟线性数组和链表不同.HashTable是高速查找的数据结构.本文中的HashTable使用链表处理数组. 该HashTable能够指定table的长度.提供了遍历的方法. 包含table的长度的选择也比較讲究. 其它c的数据结构实现.dyArray參考点击打开链接  treeStruct參考点击打开链接 cp_int32 nPrime[MAX_HASH_PRIME_ARRAY_NUM] = { 17, 37, 79, 163, 331, 673, 1361 }; 就是说table的长度来取自上

go语言如何实现类似c++中的多态功能

go语言作为编程语言中的后起之秀,在博采众长的同时又不失个性,在注重运行效率的同时又重视开发效率,不失为一种好的开发语言.在go语言中,没有类的概念,但是仍然可以用struct+interface来实现类的功能,下面的这个简单的例子演示了如何用go来模拟c++中的多态的行为. package main import "os" import "fmt" type Human interface { sayHello() } type Chinese struct {

数据结构(Java语言)——HashTable(开放定址法)简单实现

分离链接散列算法的缺点是使用一些链表.由于给新单元分配地址需要时间,因此这就导致算法的速度有些减慢,同时算法实际上还要求对第二种数据结构的实现.另有一种不用链表解决冲突的方法是尝试另外一些单元,直到找出空的单元为止.更常见的是,单元h0(x),h1(x),h2(x),...相继被试选,其中hi(x)=(hash(x)+f(i)) mod TableSize,且f(0)=0.函数f是冲突解决方法,因为所有的数据都要置于表内,所以这种解决方案所需要的表要比分离链接散列的表大.一般来说,对于不使用分离

数据结构(Java语言)——HashTable简单实现

散列表的实现通常叫做散列hashing.散列是一种用于以常数平均时间执行插入.删除和查找的技术.但是,那些需要元素间任何排序信息的树操作将不会得到有效的支持.理想的散列表数据结构只不过是一个包含一些项的具有固定大小的数组.通常查找是对项的某个部分(数据域)进行的,这部分叫做关键字.例如,项可以由一个串(作为关键字)和其它一些数据域组成.我们把表的大小记作TableSize,并将其理解为散列数据结构的一部分,而不仅仅是浮动于全局的的某个变量.通常习惯是让表从0到TableSize-1变化. 每个关

转:一个C语言实现的类似协程库(StateThreads)

http://blog.csdn.net/win_lin/article/details/8242653 译文在后面. State Threads for Internet Applications Introduction State Threads is an application library which provides a foundation for writing fast and highly scalable Internet Applications on UNIX-li

您的位置:首页 &#187; IOS &#187; iOS中全局悬浮按钮,类似IPhone中的AssistiveTouch iOS中全局悬浮按钮,类似IPhone中的AssistiveTouch

原文地址:http://blog.5ibc.net/p/86562.html 前提:当时看到别人写过这个类似AssistiveTouch的demo,但是有问题,第一改变不了位置.第二切换页面后无法使用.第三运行时偶尔会崩溃.然后自己就去度娘.论坛中都查了一些资料,然后结合起来写了这么一个demo. 思路:实现全局 需要在 AppDelegate.m 文件中 didFinishLaunchingWithOptions 方法里面实现 1.新建一个 继承于 UIWindow 的类 AssistiveT

【转】java 容器类使用 Collection,Map,HashMap,hashTable,TreeMap,List,Vector,ArrayList的区别

原文网址:http://www.360doc.com/content/15/0427/22/1709014_466468021.shtml java 容器类使用 Collection,Map,HashMap,hashTable,TreeMap,List,Vector,ArrayList的区别. 经常会看到程序中使用了记录集,常用的有Collection.HashMap.HashSet.ArrayList,因为分不清楚它们之间的关系,所以在使用时经常会混淆,以至于不知道从何下手.在这儿作了一个小例

java集合List、Set、Map总结 + HashMap/Hashtable区别

List:(有序,可以重复)通过下标索引 ----ArrayList  可变数组,随机查找 ----LinkedList    链表,任何位置插入删除快 ----Vector    效率比arraylist低,但是可以用于多线程同步 Set:(无序,不可以重复)set最多有一个null元素,因为不可以重复 ----HashSet    没有排序,不重复(顺序随机) ----LinkedHashSet    按插入排序,不重复(按插入顺序) ----TreeSet    实现Comparable接

java集合: List、Set、Map总结 + HashMap/Hashtable 差别

List:(有序,能够反复)通过下标索引 ----ArrayList  可变数组,随机查找 ----LinkedList    链表,不论什么位置插入删除快 ----Vector    效率比arraylist低.可是能够用于多线程同步 Set:(无序,不能够反复)set最多有一个null元素.由于不能够反复 ----HashSet    没有排序,不反复(顺序随机) ----LinkedHashSet    按插入排序.不反复(按插入顺序) ----TreeSet    实现Comparabl