Hash表的C++实现

头文件:

 

/*****************************************************************************
 *                                    student.h
 *
 * A student class including comparison operators.
 *
 * Zhang Ming, 2009-10
 *****************************************************************************/


#ifndef STUDENT_H
#define STUDENT_H


#include <iostream>
#include <string>


using namespace std;


namespace itlab
{

    class Student
    {

    public:

        Student() : key(0), firstName("Ming"), lastName("Zhang")
        { }

        Student( int number, const string &name1="Ming",
                             const string &name2="Zhang" )
        {
            key = number;
            firstName = name1;
            lastName = name2;
        }

        ~Student()
        { }

        inline void operator=( const Student &stu )
        {
            key = stu.key;
            firstName = stu.firstName;
            lastName = stu.lastName;
        }

        inline bool operator<( const Student &stu )
        {   return key < stu.key;   }

        inline bool operator>( const Student &stu )
        {   return key > stu.key;   }

        inline bool operator==( const Student &stu )
        {   return key == stu.key;   }

        friend istream& operator>>( istream &in, Student &stu )
        {
            in >> stu.key >> stu.lastName >> stu.firstName;
            return in;
        }

        friend ostream& operator<<( ostream &out, Student &stu )
        {
            out << stu.key << "\t"
                << stu.lastName << " " << stu.firstName << endl;
            return out;
        }

        int key;

    private:

        string firstName;
        string lastName;

    };
    // class Student

}
// namespace itlab


#endif
// STUDENT_H

 

/*****************************************************************************
 *                                    hashtable.h
 *
 * Hash table implemented by C++ template class.
 *
 * This class provides "search", "insert" and "remove" operations by using a
 * Hash Table. We use the quadratic probing method to prevent the element
 * number exceeding half of the total table size.
 *
 * Zhang Ming, 2009-10
 *****************************************************************************/


#ifndef HASHTABLE_H
#define HASHTABLE_H


#include <iostream>
#include <cstdlib>
#include <string>


using namespace std;


namespace itlab
{

    template <typename Object, typename Key>
    class HashTable
    {

    public:

        explicit HashTable( int size=7 );
        ~HashTable();

//        HashTable( const HashTable<Object, Key> &rhs );
//        HashTable<Object, Key>& operator=( const HashTable<Object, Key> &rhs );

        void makeEmpty();

        inline bool search( const Key k, Object &x ) const;
        bool insert( const Object &x );
        bool remove( const Key k, Object &x );

        enum EntryFlag { ACTIVE, EMPTY, DELETED };

    private:

        struct HashEntry
        {
            Object      element;
            EntryFlag   info;

            HashEntry( const Object &x=Object(), EntryFlag i=EMPTY )
              : element(x), info(i)
            { }
        };

        HashEntry *array;

        int currentSize;
        int tableSize;

        inline bool isActive( int currentPos ) const;
        int findPos( const Key k ) const;
        void rehash( );

        int myhash( const Key k ) const;

    };


    bool isPrime( int n );
    int  nextPrime( int n );


    #include <hashtable-impl.h>

}
// namespace itlab


#endif
// HASHTABLE_H

 

实现文件:

 

/*****************************************************************************
 *                               hashtable-impl.h
 *
 * Implementation for Hashtable class.
 *
 * Zhang Ming, 2009-10
 *****************************************************************************/


/**
 * constructors and destructor
 */
template <typename Object, typename Key>
HashTable<Object, Key>::HashTable( int size ) : tableSize(size)
{
    array = new HashEntry[tableSize];
    if( !array )
    {
        cout << "Out of memory!" << endl << endl;
        exit( 1 );
    }

    makeEmpty();
}

template <typename Object, typename Key>
HashTable<Object, Key>::~HashTable()
{
    delete []array;
}


/**
 * Make the table empty.
 */
template <typename Object, typename Key>
void HashTable<Object, Key>::makeEmpty( )
{
    currentSize = 0;
    for( int i = 0; i < tableSize; ++i )
        array[i].info = EMPTY;
}



/**
 * Searching an element with key "k" and then assign it to "x".
 */
template <typename Object, typename Key>
inline bool HashTable<Object, Key>::search( const Key k, Object &x ) const
{
    int index = findPos( k );

    if( !isActive( index ) )
        return false;
    else
    {
        x = array[index].element;
        return true;
    }
}


/**
 * Inserting an element into the table. If the number of elements
 * is greater than half of the table size, then making "re-hash".
 */
template <typename Object, typename Key>
bool HashTable<Object, Key>::insert( const Object &x )
{
    int currentPos = findPos( x.key );
    if( isActive( currentPos ) )
        return false;

    array[currentPos] = HashEntry( x, ACTIVE );
    if( ++currentSize > tableSize/2 )
        rehash( );

    return true;
}


/**
 * Removing an element with key "k" and then assign it to "x".
 */
template <typename Object, typename Key>
bool HashTable<Object, Key>::remove( const Key k, Object &x )
{
    int currentPos = findPos( k );

    if( !isActive( currentPos ) )
        return false;
    else
    {
        x = array[currentPos].element;
        array[currentPos].info = DELETED;
        currentSize--;
        return true;
    }
}


/**
 * If the current position is active, return true.
 */
template <typename Object, typename Key>
inline bool HashTable<Object, Key>::isActive( int currentPos ) const
{
    return array[currentPos].info == ACTIVE;
}


/**
 * If the current position is active, return true.
 */
template <typename Object, typename Key>
int HashTable<Object, Key>::findPos( const Key k ) const
{
    int offset = 1;
    int currentPos = myhash( k );

    while( array[currentPos].info != EMPTY &&       // these two testing
           array[currentPos].element.key != k )     // cann't be switched
    {
        currentPos += offset;
        offset += 2;
        if( currentPos >= tableSize )
            currentPos -= tableSize;
    }

    return currentPos;
}


/**
 * To ensure the number of elements is not greater than
 * half of the table size.
 */
template <typename Object, typename Key>
void HashTable<Object, Key>::rehash( )
{
    int oldTableSize = tableSize;
    HashEntry *oldArray = array;

    tableSize = nextPrime( 2*oldTableSize );
    array = new HashEntry[tableSize];
    if( !array )
    {
        cerr << "Out of memory!"  << endl << endl;
        exit( 1 );
    }

    for( int j=0; j<tableSize; ++j )
        array[j].info = EMPTY;

    currentSize = 0;
    for( int i=0; i<oldTableSize; ++i )
        if( oldArray[i].info == ACTIVE )
            insert( oldArray[i].element );

    delete []oldArray;
}


/**
 * hash mapping.
 */
template <typename Object, typename Key>
int HashTable<Object, Key>::myhash( const Key k ) const
{
    int hashValue = k % tableSize;
    if( hashValue < 0 )
        hashValue += tableSize;

    return hashValue;
}


/**
 * If "n" is a prime number, return true.
 */
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;
}


/**
 * Finding the nest prime number greater than "n".
 */
int nextPrime( int n )
{
    if( n%2 == 0 )
        n++;

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

    return n;
}

 

测试文件:

 

/*****************************************************************************
 *                               hashtable_test.cpp
 *
 * Hash table class testing.
 *
 * Zhang Ming, 2009-10
 *****************************************************************************/


#include <iostream>
#include <string>
#include <student.h>
#include <hashtable.h>


using namespace std;
using namespace itlab;


int const N = 10;


int main()
{
    int x[N] = { 3, 2, 1, 4, 5, 6, 7, 10, 9, 8 };
    int y[N] = { 3, 2, 1, 4, 5, 16, 17, 20, 19, 18 };
    Student stu;
    HashTable<Student, int> ht;

    for( int i=0; i<N; ++i )
    {
        stu.key = x[i];
        if( ht.insert( stu ) )
            cout << "Inserting success: " << stu;
        else
            cout << "Inserting failure." << endl;
    }
    cout << endl;

    for( int i=0; i<N; ++i )
        if( ht.remove( y[i], stu ) )
            cout << "Removing success: " << stu;
        else
            cout << "Removing failure." << endl;
    cout << endl;

    for( int i=0; i<N; ++i )
        if( ht.search( x[i], stu ) )
            cout << "Searching success: " << stu;
        else
            cout << "Searching failure." << endl;
    cout << endl;

    return 0;
}

 

转载于:https://my.oschina.net/zmjerry/blog/3727

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值