符号表之Hash table 实现
来源:互联网 发布:淘宝卖写真集违规吗 编辑:程序博客网 时间:2024/06/07 04:57
如有错误请指正
接口定义请参考 点击打开链接,只有接口名字不一样,所里这里不再列出了。
接口实现
#include "hash.h"#include <stdio.h>#include <stdlib.h>#include <assert.h>#include <string.h>#define ARRAY_SIZE 3// Store the bucket counts of hash tablestatic const unsigned long kBucketCount[ARRAY_SIZE] = \{1024, 2048, 666666};// Hold current Bucket sizestatic int giBucketCountIndex = 0;/* ListNode to identify the data unit under processing */typedef struct ListNode{ char* key; // Current node key void* value; // Pointer to the value which binding to the key struct ListNode* next; // Next node} ListNode;/** Association */typedef struct ListAssociation{ struct ListNode* head_node; struct ListNode* tail_node; unsigned long uiNodeLength; // The length of linked list} ListAssociation;/* HashTable to collect the hash table data */typedef struct HashTable{ struct ListAssociation** bucketTable; unsigned long uiBindingsCount; // Hold bindings size unsigned long uiBucketCount; // Hold Bucket size} HashTable;typedef struct HashTable* HashTable_t;/* Local help function* Use calloc to allocate the memory,* because it will initialize all memory bits to zero.*/static void* MyAlloc ( unsigned long size );/***Local function, if find out the pcKey return the ListAssociation*,*other return NULL*/static ListAssociation* HashTable_getListAssociation( HashTable_t oHashTable, const char* pcKey );/***Local function, if find out the pcKey return the ListNode*,*other return NULL*/static ListNode* ListAssociation_getListNode( const ListAssociation* pListAssociation, const char* pcKey );/***Local function.*If a pcKey isn’t already in the ListAssociation pointed to by *pListAssociation,inserts it into the ListAssociation and returns 1.*If not enough memory is available or pcKey already is in the *ListAssociation, the function will leave ListAssociation *unchanged and return 0.*/static int ListAssociation_put( ListAssociation* pListAssociation, const char* pcKey, const void* pvValue );/***Local function, if find out the pcKey return the ListNode*,*other return NULL*/static ListNode* HashTable_getListNode( HashTable_t oHashTable, const char* pcKey );/***Local help function,Refresh the hash table.*For the rehash function, this is the array of bucket counts: *1024, 2048, 666666. Initially, *the bucket count should be set to the first size (1024). When*HashTable_put detects that the total number of bindings exceeds the *current bucket count,1024, a rehash function should increase the *bucket count to 2048. Then as number of bindings exceeds 2048, the*bucket count should be 666666. If the binding count goes *over 666666, the bucket count should not be increased again. *If successful return 1, otherwise return 0*/static int Rehash( HashTable_t oHashTable );/*** For help Rehash().*/static int ListAssociation_put_help_rehash( ListAssociation* pListAssociation, ListNode* pListNode );/*** Update giBucketCountIndex.* In some cases(example cycle test) the giBucketCountIndex may be wrong,* so need update it to the real index.*/static int GetBucketSizeIndex( unsigned long uiBucketCounts );// HashTable_hash int HashTable_hash( const char* pcKey, int iBucketCount ){ int i; unsigned int uiHash = 0U; assert( pcKey != NULL ); for ( i = 0; pcKey[i] != '\0'; i++ ) { uiHash = uiHash * 66666 + ( unsigned int )pcKey[i]; } return ( int )( uiHash % ( unsigned int ) iBucketCount );}HashTable_t HashTable_new( void ){ HashTable_t temp = ( HashTable_t ) MyAlloc ( sizeof ( HashTable ) ); if ( temp ) { struct ListAssociation** pListAssociation = NULL; temp->uiBucketCount = kBucketCount[0];// The default Bucket size pListAssociation = ( ListAssociation** )\ MyAlloc( temp->uiBucketCount * sizeof( ListAssociation* ) ); if ( NULL == pListAssociation ) { free( temp ); return NULL; } temp->bucketTable = pListAssociation; } return temp;}void HashTable_free( HashTable_t oHashTable ){ assert ( oHashTable ); unsigned long uiBucketCount = oHashTable->uiBucketCount; unsigned i = 0; for ( i = 0; i < uiBucketCount; ++i ) { struct ListAssociation* pListAssociation = NULL; pListAssociation = oHashTable->bucketTable[i]; if ( NULL == pListAssociation ) { continue; } ListNode* temp = pListAssociation->head_node; while ( temp ) { pListAssociation->head_node = pListAssociation->head_node->next; if ( temp->key )// Release key { free ( temp->key ); } free ( temp ); // Release ListNode temp = pListAssociation->head_node; } free( pListAssociation );// Release ListAssociation pListAssociation = NULL; } free( oHashTable->bucketTable ); free ( oHashTable ); oHashTable = NULL;}int HashTable_getLength( HashTable_t oHashTable ){ return oHashTable->uiBindingsCount;}int HashTable_put( HashTable_t oHashTable, const char* pcKey, const void* pvValue ){ assert ( oHashTable ); assert ( pcKey ); assert ( pvValue ); assert ( oHashTable->uiBucketCount ); if ( 0 == strlen( pcKey ) ) { return 0; } // Check if the Bucket counts < 666666 if ( oHashTable->uiBucketCount < kBucketCount[ARRAY_SIZE - 1] ) { // If bindings counts > Bucket counts,refresh the hash table, if ( oHashTable->uiBindingsCount >= oHashTable->uiBucketCount ) { // Refresh the hash table if ( 0 == Rehash( oHashTable ) ) { return 0; } } } ListAssociation* pListAssociation = HashTable_getListAssociation( oHashTable, pcKey ); if ( NULL == pListAssociation ) // There is no ListAssociation* in table { pListAssociation = ( ListAssociation* )MyAlloc ( sizeof( ListAssociation ) ); if ( NULL == pListAssociation ) { return 0; } // Put pListAssociation into table oHashTable->bucketTable[HashTable_hash( pcKey, oHashTable->uiBucketCount )] = pListAssociation; } // Insert the bindings into ListAssociation if ( ListAssociation_put( pListAssociation, pcKey, pvValue ) ) { oHashTable->uiBindingsCount = oHashTable->uiBindingsCount + 1; return 1; } return 0;}int HashTable_contains( HashTable_t oHashTable, const char* pcKey ){ assert ( oHashTable ); assert ( pcKey ); if ( HashTable_getListNode( oHashTable, pcKey ) ) { return 1; } return 0;}void* HashTable_get( HashTable_t oHashTable, const char* pcKey ){ assert ( oHashTable ); assert ( pcKey ); ListNode* pListNode = HashTable_getListNode( oHashTable, pcKey ); if ( pListNode ) { return pListNode->value; } return NULL;}void HashTable_map( HashTable_t oHashTable, void ( *pfApply )( const char* pcKey, const void* pvValue, void* pvExtra ), const void* pvExtra ){ assert ( oHashTable ); assert ( pfApply ); assert ( pvExtra ); unsigned long uiBucketCount = oHashTable->uiBucketCount; unsigned i = 0; // The table is empty, return if ( 0 == HashTable_getLength( oHashTable ) ) { return; } for ( i = 0; i < uiBucketCount; ++i ) { ListAssociation* pListAssociation = oHashTable->bucketTable[i]; if ( NULL == pListAssociation ) { continue; } ListNode* pListNode = pListAssociation->head_node; while ( pListNode ) { assert ( pListNode->key ); assert ( pListNode->value ); pfApply( pListNode->key, pListNode->value, ( void* )pvExtra ); pListNode = pListNode->next; } } return;}void* HashTable_replace( HashTable_t oHashTable, const char* pcKey, const void* pvValue ){ assert ( oHashTable ); assert ( pcKey ); void* value = NULL; ListNode* pListNode = HashTable_getListNode( oHashTable, pcKey ); if ( pListNode ) { value = pListNode->value; pListNode->value = ( void* )pvValue; } return value;}void* HashTable_remove( HashTable_t oHashTable, const char* pcKey ){ assert ( oHashTable ); assert ( pcKey ); ListAssociation* pListAssociation = HashTable_getListAssociation( oHashTable, pcKey ); if ( NULL == pListAssociation ) { return NULL; } void* value = NULL; ListNode* temp = pListAssociation->head_node; ListNode* pre_node = NULL; /* *The key-value maybe has been removed *or has not inserted successfully */ if ( NULL == temp ) { return NULL; } if ( 0 == strcmp ( pcKey, temp->key ) ) // Head node is the node which need to be removed { value = temp->value; pListAssociation->head_node = temp->next; free ( temp->key ); free ( temp ); pListAssociation->uiNodeLength = pListAssociation->uiNodeLength - 1; oHashTable->uiBindingsCount = oHashTable->uiBindingsCount - 1; return value; } while ( 1 ) { pre_node = temp; temp = temp->next; if ( NULL == temp ) { return NULL; } if ( 0 == strcmp ( pcKey, temp->key ) ) // Find it { pre_node->next = temp->next; value = temp->value; // Do not forget to release the memory free ( temp->key ); free ( temp ); // Update the counts pListAssociation->uiNodeLength = pListAssociation->uiNodeLength - 1; oHashTable->uiBindingsCount = oHashTable->uiBindingsCount - 1; return value; } } return NULL;}static void* MyAlloc ( unsigned long size ){ void* tmp; tmp = ( void* ) calloc ( size, sizeof ( char ) ); assert( tmp ); return tmp;}static ListAssociation* HashTable_getListAssociation( HashTable_t oHashTable, const char* pcKey ){ assert ( oHashTable ); assert ( pcKey ); if ( 0 == strlen( pcKey ) ) { return NULL; } int iHash_key = -1; iHash_key = HashTable_hash( pcKey, oHashTable->uiBucketCount ); assert( iHash_key >= 0 ); return oHashTable->bucketTable[iHash_key];}static ListNode* ListAssociation_getListNode( const ListAssociation* pListAssociation, const char* pcKey ){ assert ( pListAssociation ); assert ( pcKey ); if ( 0 == strlen( pcKey ) ) { return NULL; } ListNode* pListNode = pListAssociation->head_node; while ( pListNode ) { if ( 0 == strcmp ( pcKey, pListNode->key ) ) { return pListNode; } pListNode = pListNode->next; } return NULL;}static int ListAssociation_put( ListAssociation* pListAssociation, const char* pcKey, const void* pvValue ){ assert ( pListAssociation ); assert ( pcKey ); assert ( pvValue ); if ( ListAssociation_getListNode( pListAssociation, pcKey ) ) { return 0; } else { ListNode* new_node = ( ListNode* )MyAlloc ( sizeof( ListNode ) ); if ( NULL == new_node ) { return 0; } char* key = ( char* ) MyAlloc ( strlen ( pcKey ) + 1 ); if ( NULL == key ) { free( new_node ); return 0; } new_node->key = key; strcpy ( new_node->key, pcKey ); new_node->value = ( void* )pvValue; //?? if ( 0 == pListAssociation->uiNodeLength ) // The list is empty { pListAssociation->head_node = new_node; pListAssociation->tail_node = new_node; pListAssociation->uiNodeLength = 1; return 1; } if ( 1 == pListAssociation->uiNodeLength ) // Only one key-value in list { pListAssociation->head_node->next = new_node; pListAssociation->tail_node = new_node; pListAssociation->uiNodeLength = 2; return 1; } else // More than one key-value in list { pListAssociation->tail_node->next = new_node; pListAssociation->tail_node = new_node; pListAssociation->uiNodeLength += 1; return 1; } }}static ListNode* HashTable_getListNode( HashTable_t oHashTable, const char* pcKey ){ assert ( oHashTable ); assert ( pcKey ); if ( 0 == strlen( pcKey ) ) { return NULL; } ListAssociation* pListAssociation = NULL; if ( 0 == HashTable_getLength( oHashTable ) ) { return NULL; } pListAssociation = HashTable_getListAssociation( oHashTable, pcKey ); if ( NULL == pListAssociation ) { return NULL; } return ListAssociation_getListNode( pListAssociation, pcKey );}static int Rehash( HashTable_t oHashTable ){ assert( oHashTable ); assert( oHashTable->uiBindingsCount >= oHashTable->uiBucketCount ); giBucketCountIndex = GetBucketSizeIndex( oHashTable->uiBucketCount ); assert( giBucketCountIndex >= 0 ); unsigned long uiBucketCounts = 0; if ( ( ARRAY_SIZE - 1 ) == giBucketCountIndex ) { return 1; } ++giBucketCountIndex; uiBucketCounts = kBucketCount[giBucketCountIndex]; // Create a new ListAssociation** base on uiBucketCounts struct ListAssociation** pNewListAssociation = NULL; pNewListAssociation = ( ListAssociation** )MyAlloc( uiBucketCounts * sizeof( ListAssociation* ) ); if ( NULL == pNewListAssociation ) { return 0; } // Update the old ListAssociation** to new ListAssociation** { unsigned long uiBucketCount = oHashTable->uiBucketCount; unsigned long i = 0; for ( i = 0; i < uiBucketCount; ++i ) { struct ListAssociation* pOldListAssociation = NULL; pOldListAssociation = oHashTable->bucketTable[i]; if ( NULL == pOldListAssociation ) { continue; } ListNode* pTempListNode = pOldListAssociation->head_node; // Iterate current ListNode and update the bindings to new table while ( pTempListNode ) { int iHash_key = -1; iHash_key = HashTable_hash( pTempListNode->key, uiBucketCounts ); assert( iHash_key >= 0 ); ListAssociation* pListAssociation = pNewListAssociation[iHash_key]; if ( NULL == pListAssociation ) // There is no ListAssociation* in table { pListAssociation = ( ListAssociation* )MyAlloc ( sizeof( ListAssociation ) ); if ( NULL == pListAssociation ) { return 0; } // Put ListAssociation* into new table pNewListAssociation[iHash_key] = pListAssociation; } pOldListAssociation->head_node = pOldListAssociation->head_node->next; if ( 0 == ListAssociation_put_help_rehash( pListAssociation, pTempListNode ) ) { return 0; } pTempListNode = pOldListAssociation->head_node; } // Do not forget to release memory free( pOldListAssociation ); pOldListAssociation = NULL; } } free( oHashTable->bucketTable ); // Update for the new BucketSize oHashTable->bucketTable = pNewListAssociation; oHashTable->uiBucketCount = uiBucketCounts; return 1;}static int ListAssociation_put_help_rehash( ListAssociation* pListAssociation, ListNode* pListNode ){ assert ( pListAssociation ); assert ( pListNode ); if ( ListAssociation_getListNode( pListAssociation, pListNode->key ) ) { return 0; } else { if ( 0 == pListAssociation->uiNodeLength ) // The list is empty { pListAssociation->head_node = pListNode; pListAssociation->tail_node = pListNode; pListAssociation->tail_node->next = NULL; pListAssociation->uiNodeLength = 1; return 1; } // Only one key-value in list if ( 1 == pListAssociation->uiNodeLength ) { pListAssociation->head_node->next = pListNode; pListAssociation->tail_node = pListNode; pListAssociation->tail_node->next = NULL; pListAssociation->uiNodeLength = 2; return 1; } else // More than one key-value in list { pListAssociation->tail_node->next = pListNode; pListAssociation->tail_node = pListNode; pListAssociation->tail_node->next = NULL; pListAssociation->uiNodeLength += 1; return 1; } }}static int GetBucketSizeIndex( unsigned long uiBucketCounts ){ int i = 0; for ( i = 0; i < ARRAY_SIZE; ++i ) { if ( uiBucketCounts == kBucketCount[i] ) { giBucketCountIndex = i; return giBucketCountIndex; } } return -1;}
0 0
- 符号表之Hash table 实现
- Hash Table 的实现
- google hash table ------稀疏hash表之sparse hashtable
- 数据结构实现之Table(符号表,内部存储key-value对)
- C++简单实现hash table
- 符号表之List 实现
- Oracle之表的种类(heap,partition table,glable temp table,orgination index table,cluster sort hash table)
- Hash表——The Hash table
- 数据结构——简单Hash Table实现
- kernel 中的hash table的实现
- C++ hash table 的编程实现
- 哈希表(Hash Table)原理及其实现
- C/C++ 实现哈希表(hash table)
- 符号表(Symbol Table)
- 数据结构之---散列表(hash table)
- LeetCode之Hash Table题目汇总
- Hash Table
- Hash Table
- 谷歌官方教程:Android UI设计技巧
- php取出数组内指定的值
- Android动态调试
- VS2010解决方案转换成VS2008
- error LNK2019: 无法解析的外部符号 __imp__PlaySoundA@12,该符号在函数 .... 中被引用....
- 符号表之Hash table 实现
- Google高级搜索技巧
- Spring Data JPA初使用
- Mysql查询表中指定字段出现字符串次数
- TCP/IP各个层功能
- 软件定制开发
- IDEA 创建maven工程,并提交到svn
- java当中的executor
- 为什么使用补码