HashTable(散列表)的实现代码及测试代码

/// 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; // 打开内存操作的提示
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值