实现一组可供操作的ADT (hash-map)

tan625747 2010-03-31 10:14:45
实现一组可供操作的ADT(变长数组,链表,字典(map),hash-map,),以dll或者代码的形式提供给我调用,要尽量优化到可以处理大量不同类型的数据而保持一定的效率

这个怎么实现啊,用什么方法,可以实现。
...全文
51 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
chinalnmhx 2010-10-06
  • 打赏
  • 举报
回复
xiexie
冻结 2010-03-31
  • 打赏
  • 举报
回复
STL找,找不到,boost找。
tan625747 2010-03-31
  • 打赏
  • 举报
回复
我知道了,谢谢你们了
cattycat 2010-03-31
  • 打赏
  • 举报
回复
上面贴的是个头文件,用的时候包含进去就行,是从网上找的,用到了stl的一些库函数,vc中的stl没有hashmap头文件,所以可以按sgi-stl类似的写一个,相比那个这个实现简单多了,没有考虑复杂的迭代器等。基本的插入和删除,查找函数还是实现了。
cattycat 2010-03-31
  • 打赏
  • 举报
回复
/* 本程序是哈希表实现的 hash_map容器类,接口与STL hash_map类似
*/

#ifndef __my_hash_map__
#define __my_hash_map__

#include<string>
#include<algorithm> //需要lower_bound函数



//负载系数,当哈希表中元素个数/哈希表容量 > 负载系数 时将重建更大的哈希表
const double __load_factor = 0.75 ;

//素数表的大小
const int __num_prime = 28 ;

// 0至UINT_MAX内部分素数,哈希表的大小为素数可以减少哈希函数的冲突
const unsigned long __prime_list [ __num_prime ] =
{
53, 97, 193, 389, 769,
1543, 3079, 6151, 12289, 24593,
49157, 98317, 196613, 393241, 786433,
1572869, 3145739, 6291469, 12582917, 25165843,
50331653, 100663319, 201326611, 402653189, 805306457,
1610612741, 3221225473ul, 4294967291ul
};
//在 __prime_list 中二分查找第一个不小于n 的素数,若查找不到则返回最后一个
inline unsigned long __next_prime ( unsigned long n )
{
const unsigned long * first = __prime_list ;
const unsigned long * last = __prime_list + __num_prime ;
const unsigned long * pos = lower_bound( first , last , n ) ;
return ( pos == last )? *( last - 1 ) : *pos ;
}

template <class T>
class myHashNode
{
public:
myHashNode()
{
key = "" ;
used = false ;
nextBucket = NULL ;
}
myHashNode( string str, T v )
{
key = str ;
value = v ;
nextBucket = NULL ;
used = true ;
}
bool isUsed() { return used ; }
void setUsed() { used = true ; }

string key ;
T value ;
myHashNode * nextBucket ;
bool used ;
};


template <class T>
class myHashMap
{
public:
myHashMap()
{
hash = new myHashNode<T> [ __prime_list[0] ] ;
__size = __prime_list[0] ;
__num_node = 0 ;
}

myHashNode<T> * begin() const { return hash ; }

myHashNode<T> * end( ) const { return hash + __size ; }

unsigned long capaticy() const { return __size ; }//返回哈希表的容量

unsigned long size() const { return __num_node ; }//哈希表已有的元素的个数

T get( myHashNode<T> * cur) const { return cur->value ; }

unsigned long hash_function( string str , unsigned long SIZE) ;// 作用:对字符串str 返回哈希函数值

void insert( string str, T value ) ; // 插入关键字为str,值为value的组

myHashNode<T>* find( string str ) ; //查找关键字为str的组,返回其指针 ,若查找不到则返回“超出末端”的指针

void erase( string str ) ; //删除关键字为str的组

void resize( ) ; //扩大哈希表的容量

bool empty( ) { return __num_node == 0 ; } //判断哈希表是否为空

void clear( ) ; //清空哈希表的所有元素

T& operator[] ( string str ) ; //重载[]运算符 ,若[]中的key不存在,则在表中插入一个关键字为key的新元素

private:
myHashNode<T> *hash ;
unsigned long __size ;
unsigned long __num_node ;
};


/* 作用:对字符串str 返回哈希函数值 */
/* 哈希函数值 = 256^(n-1)* (str[0]-'0') + 256^(n-2) *(str[1]-'0') + …… +256^0 *(str[n-1]-'0' ) MOD SIZE */
template<class T>
unsigned long myHashMap<T>::hash_function( string str , unsigned long SIZE)
{
unsigned long uper = UINT_MAX / 256 ;
unsigned long temp = 0 ;
unsigned long last = str.size() - 1 ;
while( last !=0 )
{
temp *= 256 ;
temp += str[ last ] ;

if( temp >= uper ) //确保不超出Unsigned long 的范围
temp %= SIZE ;
--last ;
}
temp *= 256 ;
temp += str[0] ;
temp %= SIZE ;
return temp ;
}

/*查找关键字为str的组,返回其指针 ,若查找不到则返回“超出末端”的指针 */
template<class T>
myHashNode<T>* myHashMap<T>::find( string str )
{
unsigned long pos = hash_function( str , __size ) ;

if( hash[ pos ].isUsed() == true && hash[ pos ].key == str )
return hash + pos ;

myHashNode<T> * cur = hash[pos].nextBucket ;
while( cur != NULL )
{
if( cur->isUsed() && cur->key == str )
return cur ;
cur = cur->nextBucket ;
}
return hash + __size ;
}


template<class T>
void myHashMap<T>::insert( string str, T v ) // 插入关键字为str,值为v的组
{
if( (float)__num_node/(float)__size > __load_factor ) //当前容量已经超过负载系数,所以重建哈希表
resize( ) ;

++ __num_node ;
unsigned long pos = hash_function( str , __size ) ;

if( hash[ pos].used == false || hash[pos].key == str ) //覆盖旧值
{
hash[ pos ].key = str ;
hash[ pos ].value = v ;
hash[ pos ].used = true ;
return ;
}

myHashNode<T> * cur = hash[ pos ].nextBucket ;
if( cur == NULL )
{
myHashNode<T> * newnode = new myHashNode<T>( str , v ) ;
hash[ pos ].nextBucket = newnode ;
return ;
}
while( cur->nextBucket != NULL && cur->nextBucket->key != str && cur->nextBucket->used == true )
cur = cur->nextBucket ;

if( cur->nextBucket == NULL )
{
myHashNode<T> * newnode = new myHashNode<T>( str , v ) ;
cur->nextBucket = newnode ;
return ;
}
if( cur->nextBucket->used == false ) //找到一个已经被删除的元组,覆盖旧关键字和旧值
{
cur->nextBucket->key = str ;
cur->value = v ;
cur->used = true ;
return ;
}
cur->nextBucket->value = v ; //查找到关键字相同的组,覆盖旧值
return ;
}

/*扩大哈希表的容量 */
/*先分配一块更大的空间,然后将原表中的元素逐一哈希到新表中 */
template <class T>
void myHashMap<T>::resize( )
{
unsigned long newSize= __next_prime( 2*__num_node) ; //增大容量

myHashNode<T> * t = new myHashNode<T>[ newSize ] ;

unsigned long i ;
for( i = 0 ; i< __size ; ++i )
{
if( hash[i].isUsed() )
{
//计算新的哈希函数值 ,然后插入新表中
unsigned long pos = hash_function( hash[i].key ,newSize ) ;

//新表中对应的位置未被占据
if( !t[pos].isUsed() )
{
t[pos].key = hash[i].key ;
t[pos].value = hash[i].value ;
t[pos].setUsed() ;
}
else //已被占据,插入到链表中
{
myHashNode<T> * cur = &t[pos] ;

while( cur->nextBucket !=NULL ) //由于是新表,所以链表中不存在被标志为删除的节点
cur = cur->nextBucket ;
myHashNode<T> *newNode = new myHashNode<T>( hash[i].key , hash[i].value ) ;
cur->nextBucket = newNode ;
}
}

//将原链表中的元素插入新的哈希表
myHashNode<T> * c = hash[i].nextBucket ;
while( c !=NULL )
{
if( c->isUsed() )
{
unsigned long pos = hash_function( c->key ,newSize ) ;

//新表中对应的位置未被占据
if( !t[pos].isUsed() )
{
t[pos].key = c->key ;
t[pos].value = c->value ;
t[pos].setUsed() ;
}
else //已被占据,插入到链表中
{
myHashNode<T> * cur = &t[pos] ;
while( cur->nextBucket !=NULL ) //由于是新表,所以链表中不存在被标志为删除的节点
cur = cur->nextBucket ;
myHashNode<T> *newNode = new myHashNode<T>( c->key , c->value ) ;
cur->nextBucket = newNode ;
}
}
c = c->nextBucket ;
}
}

//回收原哈希表的内存空间
clear( ) ;//删除连接的所有链表

delete []hash ; //释放旧空间,指向新的空间
hash = t ;
__size = newSize ;
}

/*删除关键字为str的组 */
template< class T >
void myHashMap<T>::erase( string str )
{
myHashNode<T> * cur = find( str ) ; //先检查str是否存在于表中
if( cur == end() )
return ;

-- __num_node ;

cur->used = false ; //并不删除,只是将该节点设置为未被使用的状态
return ;
}

/* 重载[] 运算符 */
/* 若 []中的key不存在,则在表中插入一个关键字为key的新元素 */
template<class T>
T& myHashMap<T>::operator[] ( string str )
{
myHashNode<T> *cur = find( str ) ;
if( cur != end() )
return cur->value ;
else
{
T *temp = new T ; //这里注意要用new,否则会出现未初始化的错误

insert( str , *temp );
cur = find( str ) ;
return cur->value ;
}
}

/* 清空哈希表的所有元素 */
/* 实现方法:将所有链表删除, 数组hash 上的元素则设置为未被使用 */
template< class T >
void myHashMap<T>::clear( )
{
myHashNode<T> * cur = NULL ;
myHashNode<T> * next = NULL ;
for(unsigned int i=0 ; i<__size ; ++i ) //删除挂接的所有链表
{
hash[ i ].used = false ;

cur = hash[i].nextBucket;
next = cur ;

while( cur != NULL && next != NULL )
{
next = cur->nextBucket ;
delete cur ;
cur = next ;
}
}
__num_node = 0 ;
}

#endif
tan625747 2010-03-31
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 freezezdj 的回复:]

STL找,找不到,boost找。
[/Quote]

这个要具体实现

64,680

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧