/// HashTable 的实现代码及测试代码
/// 在VC8.0下编译通过
#ifndef _DS_HashTable_H_
#define _DS_HashTable_H_
#include <vector>
using namespace std;
#include "DebugUtil.h"
namespace DataStructures
{
inline unsigned int HashString( const char* key )
{
Assert(key != 0);
unsigned int h = 0;
for (; *key; key++)
{
h = (h<<2) + h + *key;
}
return h;
}
inline unsigned int HashWstring( const wchar_t* key )
{
Assert(key != 0);
unsigned int h = 0;
for (; *key; key++)
{
h = (h<<2) + h + *key;
}
return h;
}
/// HashTable内部维护的是data_type的指针
/// 解决冲突的方法: 单向链表
template <class data_type, unsigned int (*hash_function)(const data_type&) >
class HashTable
{
public:
struct HashTableNode
{
HashTableNode() : pData(0),pNext(0) {}
data_type* pData;
HashTableNode* pNext;
};
HashTable()
{
}
/*!
/brief
构造函数
/param
size : 大小
/param
auto_delete : 是否管理传进来的指针,在HashTable清空的时候,自动施放所管理的对象的内存
*/
HashTable( unsigned int size, bool auto_delete )
{
Assert( size>0 );
m_Nodes.resize( size );
m_AutoDelete = auto_delete;
}
/*!
/brief
析构函数,清空所有结点
/param
*/
~HashTable()
{
Clear();
}
/*!
/brief
初始化HashTable
/param
size : 大小
/param
auto_delete : 是否管理传进来的指针,在HashTable情况的时候,自动施放所管理的对象的内存
*/
void Initialize( unsigned int size, bool auto_delete )
{
Assert( size>0 );
Clear();
m_Nodes.resize( size );
m_AutoDelete = auto_delete;
}
/*!
/brief
HashTable的大小
/param
*/
size_t Size() const
{
return m_Nodes.size();
}
/*!
/brief
是否在清空的时候,自动施放管理的对象的内存
/param
*/
bool IsAutoDelete() const
{
return m_AutoDelete;
}
/*!
/brief
返回一个节点
/param
index : 在HashTable里的索引
*/
const HashTableNode& Get( unsigned int index ) const
{
Assert( index < Size() );
return m_Nodes[index];
}
/*!
/brief
添加一个对象,如果Hash值冲突,则在已有节点后面添加后续节点
/param
pData : 对象指针
*/
unsigned int Add( data_type* pData )
{
//data_type* pData = &data;
unsigned int index = hash_function( *pData );
index = index % Size();
if( m_Nodes[index].pData == 0 )
{
m_Nodes[index].pData = pData;
}
else
{
HashTableNode* p = &m_Nodes[index];
while( p->pNext != 0 )
{
p = p->pNext;
if( p->pData == 0 ) // 已有空位
{
p->pData = pData;
return index;
}
}
p->pNext = new HashTableNode(); // 新增一个列表节点
p->pNext->pData = pData;
p->pNext->pNext = 0;
}
return index;
}
/*!
/brief
移除一个对象
/param
pData : 对象指针
*/
bool Remove( data_type* pData )
{
//data_type* pData = &data;
unsigned int index = hash_function( *pData );
index = index % Size();
HashTableNode* p = &m_Nodes[index];
while( p != 0 )
{
if( *(p->pData) == *pData )
{
delete p->pData;
p->pData = 0; //节点不删除,设置成空位
return true;
}
p = p->pNext;
}
return false;
}
/*!
/brief
清空所有节点
/param
*/
void Clear()
{
for( unsigned int i=0; i<Size(); ++i )
{
HashTableNode* p = &m_Nodes[i];
vector<HashTableNode*> node_list; //子列表
while( p->pNext != 0 )
{
node_list.push_back( p->pNext );
p = p->pNext;
}
for( unsigned int j=0; j<node_list.size(); ++j )
{
if( m_AutoDelete && node_list[j]->pData != 0 )
{
delete node_list[j]->pData;
node_list[j]->pData = 0;
}
delete node_list[j];
}
node_list.clear();
if( m_AutoDelete && m_Nodes[i].pData != 0 )
{
delete m_Nodes[i].pData;
m_Nodes[i].pData = 0;
}
}
m_Nodes.clear();
}
private:
vector<HashTableNode> m_Nodes;
bool m_AutoDelete;
};
}
#endif
/// HashTable 的测试代码
#include <iostream>
#include <string>
#include <vector>
using namespace std;
#include <assert.h> //assert
#include <stdlib.h> //rand srand
#include <time.h> //time
#include "DS_HashTable.h"
static bool s_print_memop = true; // 是否显示内存操作
class Data
{
public:
Data( const string& name ) : Name(name)
{
if( s_print_memop )
printf( "new Data : %s/n", Name.c_str() );
}
~Data()
{
if( s_print_memop )
printf( "delete Data : %s/n", Name.c_str() );
}
string Name;
};
unsigned int data_hash_function( const Data& data )
{
return DataStructures::HashString( data.Name.c_str() );
}
void PrintHashTable( const DataStructures::HashTable<Data,data_hash_function>& table )
{
printf( "Begin PrintHashTable :/nSize = %d/n", table.Size() );
for( unsigned int i=0; i<table.Size(); ++i )
{
const DataStructures::HashTable<Data,data_hash_function>::HashTableNode& node = table.Get( i );
if( node.pData != 0 )
{
Data* pData = node.pData;
printf( "%d : %s", i, pData->Name.c_str() );
DataStructures::HashTable<Data,data_hash_function>::HashTableNode* pNode = node.pNext;
while( pNode != 0 )
{
if( pNode->pData != 0 )
printf( " ->%s", pNode->pData->Name.c_str() );
else
printf( " ->0" );
pNode = pNode->pNext;
}
printf( "/n" );
}
}
printf( "End PrintHashTable : /n/n" );
}
string RandomString( int max_length )
{
string ret;
int length = ::rand()%max_length + 1;
for( int i=0; i<length; ++i )
{
char c = (char)(::rand()%26)+'a';
ret += c;
}
return ret;
}
void main()
{
const int HashTableSize = 100;
srand( (unsigned int)time(0) ); // 设置随机数种子
/// 测试内存操作
DataStructures::HashTable<Data,data_hash_function> hash_table( HashTableSize, true );
hash_table.Add( new Data("Fish") );
hash_table.Add( new Data("Mx") );
hash_table.Add( new Data("Feng") );
hash_table.Add( new Data("YangJianfei") );
PrintHashTable( hash_table );
hash_table.Clear();
PrintHashTable( hash_table );
Data data_0("_Fish");
Data data_1("_Mx");
Data data_2("_Feng");
Data data_3("_YangJianfei");
hash_table.Initialize( HashTableSize, false ); //不管理对象的内存
hash_table.Add( &data_0 );
hash_table.Add( &data_1 );
hash_table.Add( &data_2 );
hash_table.Add( &data_3 );
PrintHashTable( hash_table );
hash_table.Clear();
//assert( data_0 == 0 );
s_print_memop = false; // 关掉内存操作的提示
hash_table.Initialize( HashTableSize, true );
for( int i=0; i<HashTableSize; ++i )
{
hash_table.Add( new Data(RandomString(32)) );
}
PrintHashTable( hash_table );
hash_table.Clear();
s_print_memop = true; // 打开内存操作的提示
}