1004. Hashing

Description

Implement the following Hash class using separate chaining.

template <typename HashedObj>
class HashTable
{
  public:
     HashTable(int (* h)(HashedObj x), int size = 101 )
      : currentSize( 0 ), hash(h)
      { theLists.resize( size ); }

    bool contains( const HashedObj & x ) const

// If x is in the table, it returns true, otherwise, it returns false.
    {
//insert here.        

    }

    void makeEmpty( )
    {
        for( int i = 0; i < theLists.size( ); i++ )
            theLists[ i ].clear( );
    }

    bool insert( const HashedObj & x )

//Insert key x  if x is not in the table and return true. Otherwise, return false and do nothing.  If the table is full, you will call rehash.
    {
//insert here.                   

          }

    bool remove( const HashedObj & x )

//If x is present in the table, remove it and return true. Otherwise, return false. 
    {
//insert here.        

    }

  private:
    vector<list<HashedObj> > theLists;   // The array of Lists
    int  currentSize;
    int (*hash)(HashedObj x); //hash function

        int myhash( const HashedObj & x ) const
    {
        int hashVal = hash( x );

        hashVal %= theLists.size( );
        if( hashVal < 0 )
            hashVal += theLists.size( );

        return hashVal;
    }

 void rehash( )
    {
        vector<list<HashedObj> > oldLists = theLists;

            // Create new double-sized, empty table
        theLists.resize( nextPrime( 2 * theLists.size( ) ) );
        for( int j = 0; j < theLists.size( ); j++ )
            theLists[ j ].clear( );

            // Copy table over
        currentSize = 0;
        for( int i = 0; i < oldLists.size( ); i++ )
        {
            list<HashedObj>::iterator itr = oldLists[ i ].begin( );
            while( itr != oldLists[ i ].end( ) )
                insert( *itr++ );
        }
    }
};

 
 
Hint

The constructor HashTable has two parameters: the first one specifies your hash function and the second one specifies the size of the hash table. 

For example, you may create a hash table like the following:

HashTable t(h, 10007);

where h is a hash function you have defined.  

You may use the following functions:

 

bool isPrime( int n )
{
    if( n == 2 || n == 3 )
        return true;

    if( n == 1 || n % 2 == 0 )
        return false;

    for( int i = 3; i * i <= n; i += 2 )
        if( n % i == 0 )
            return false;

    return true;
}

int nextPrime( int n )
{
    if( n % 2 == 0 )
        n++;

    for( ; !isPrime( n ); n += 2 )
        ;

    return n;
}


题目要求实现一个哈希类。此处需要注意的是:

1、在类的成员函数后加const,就表明这个函数是不能改变类的成员变量,相当于给this指针加上了const修饰,也不能调用其他非const成员函数,否则编译器会报错;所以在调用与成员变量有关的迭代器时,迭代器类型是const;

2、容器中的类型为模板类型时,在使用迭代器是也要在前面加上 typename;

3、函数指针:是指向函数的指针变量,有了指向函数的指针变量后,可用该指针变量调用函数,函数指针有两个用途:调用函数和做函数的参数;

4、标准库中的list容器有push_back, push_front, pop_back, pop_front;


#include <iostream>
#include <vector>
#include <list>
using namespace std;

bool isPrime( int n )
{
    if( n == 2 || n == 3 )
        return true;
    
    if( n == 1 || n % 2 == 0 )
        return false;
    
    for( int i = 3; i * i <= n; i += 2 )
        if( n % i == 0 )
            return false;
    
    return true;
}

int nextPrime( int n )
{
    if( n % 2 == 0 )
        n++;
    
    for( ; !isPrime( n ); n += 2 )
        ;
    
    return n;
}

template <typename HashedObj>
class HashTable
{
public:
    HashTable(int (* h)(HashedObj x), int size = 101 )
    : currentSize( 0 ), hash(h)
    { theLists.resize( size ); }
    
    //任何不会修改数据成员的函数都应该声明为const类型。如果在编写const成员函数时,不慎修改了数据成员,或者调用了其它非const成员函数,编译器将指出错误,这无疑会提高程序的健壮性,相当于给this指针加上了const修饰。
    bool contains( const HashedObj & x ) const
    
    // If x is in the table, it returns true, otherwise, it returns false.
    {
        int key = myhash(x);
        //模板类型的迭代器,声明时前面要加“typename”,注意迭代器类型是const
        typename list<HashedObj>::const_iterator it = theLists[key].begin();
        while (it != theLists[key].end()) {
            if (x == *it) {
                return true;
            }
            it++;
        }
        return false;
    }
    
    void makeEmpty()
    {
        for( int i = 0; i < theLists.size( ); i++ )
            theLists[ i ].clear( );
    }
    
    bool insert( const HashedObj & x )
    
    //Insert key x  if x is not in the table and return true. Otherwise, return false and do nothing.  If the table is full, you will call rehash.
    {
        if (contains(x)) {
            return false;
        }
        if (currentSize + 1 > theLists.size()) {
            rehash();
        }
        int key = myhash(x);
        theLists[key].push_back(x);
        currentSize++;
        return true;
    }
    
    bool remove( const HashedObj & x )
    
    //If x is present in the table, remove it and return true. Otherwise, return false.
    {
        if (!contains(x)) {
            return false;
        }
        int key = myhash(x);
        typename list<HashedObj>::iterator it = theLists[key].begin();
        while (it != theLists[key].end()) {
            if (x == *it) {
                theLists[key].erase(it);
                return true;
            }
            it++;
        }
    }
    
private:
    vector<list<HashedObj> > theLists;   // The array of Lists
    int  currentSize;
    int (*hash)(HashedObj x); //hash function
    
    int myhash( const HashedObj & x ) const
    {
        int hashVal = hash( x );
        
        hashVal %= theLists.size( );
        if( hashVal < 0 )
            hashVal += theLists.size( );
        
        return hashVal;
    }
    
    void rehash( )
    {
        vector<list<HashedObj> > oldLists = theLists;
        
        // Create new double-sized, empty table
        theLists.resize( nextPrime( 2 * theLists.size( ) ) );
        for( int j = 0; j < theLists.size( ); j++ )
            theLists[ j ].clear( );
        
        // Copy table over
        currentSize = 0;
        for( int i = 0; i < oldLists.size( ); i++ )
        {
            typename list<HashedObj>::iterator itr = oldLists[i].begin();
            while( itr != oldLists[ i ].end( ) )
                insert( *itr++ );
        }
    }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值