使用重载打印HashTable时出现奇怪的输出?

时间:2014-03-19 17:24:45

标签: c++ vector stream operator-overloading hashtable

我正在使用线性探测工作一个简单的HashTable程序。

HashTable包含我已定义的Symbol类的对象。我刚刚完成了print()函数的编写,它遍历了对象的向量,它可以工作....但....它还附加了一个" 0:1"零星地输出。

我认为这可能与"<<"的重载有关。在HashTable类中的Symbol类和HashEntry结构中的stream运算符。

我已经附加了我的LinearProbing.h,Driver.cpp,Symbol.h和我的输出。

输出:

 : 0
 : 1

address : 6
 : 0

 : 0
 : 1

greeting : 6
 : 0

max2 : 3
 : 0

 : 0
 : 1

studentID : 1
 : 0

count : 2
 : 1

pi : 5
 : 1

 : 0
 : 1

city : 6
 : 0

debt : 5
 : 0

name : 6
 : 1

num : 2
 : 0

myDouble : 5
 : 1

 : 0
 : 1

gpa : 4
 : 1

ID : 1
 : 0

city : 6
 : 1

 : 0
 : 1

 : 0
 : 1

 : 0
 : 1

max : 3
 : 0

count : 2
 : 0

ch2 : 0
 : 0

myFloat : 4
 : 0

county : 6
 : 0

ch : 0
 : 0

 : 0
 : 1

 : 0
 : 1

 : 0
 : 1

state : 6
 : 0

 : 0
 : 1

myDouble : 5
 : 0

name : 6
 : 0

pi : 5
 : 0

 : 0
 : 1

salary : 5
 : 0

gdp : 5
 : 0

 : 0
 : 1

 : 0
 : 1

gpa : 4
 : 0

 : 0
 : 1

LinearProbing.h:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include "Symbol.h"

using namespace std;

int nextPrime( int n );
bool isPrime( int n );
size_t hasher(const string & key);

template<typename string>
class thehash2
{
public:
    size_t operator()(const string & key)
    {
        size_t hashVal = 0;
        for(char ch : key)
            hashVal = 37 * hashVal + ch;
        return hashVal;
    }
};

template<typename Symbol>
class thehash
{
public:
    size_t operator()(const Symbol & item)
    {
        static thehash2<string> hf;
        return hf(item.getData());
    }
};

template<typename HashedObj>
class HashTable
{
public:
    explicit HashTable(int TABLE_SIZE)
    {
        currentSize = 0;
        array.resize(TABLE_SIZE);
    }
    void makeEmpty()
    {
        currentSize = 0;
        for(int i = 0; i < array.size(); i++)
            array[i].info = EMPTY;
    }
    bool contains(const HashedObj & x) const
    {
        return isActive(findPos(x));
    }
    bool insert(const HashedObj & x)
    {
        int currentPos = findPos(x);
        if(isActive(currentPos))
            return false;

        array[currentPos] = HashEntry(x, ACTIVE);

        if(++currentSize > array.size() / 2)
            rehash();
        return true;
    }
    bool remove(const HashedObj & x)
    {
        int currentPos = findPos(x);
        if(!isActive(currentPos))
            return false;
        array[currentPos].info = DELETED;
        return true;
    }

    void print()
    {
        typename vector<HashEntry>::iterator vIter = array.begin();
        while(vIter != array.end())
        {
            cout << *vIter << "\n";
            ++vIter;
        }
    }

    enum EntryType{ ACTIVE, EMPTY, DELETED };
private:
    struct HashEntry
    {
        HashedObj element;
        EntryType info;

        HashEntry(const HashedObj & e = HashedObj(), EntryType i = EMPTY) : element(e), info(i) {}

        friend ostream & operator <<(ostream & os, HashEntry & hashentry) //overloaded to print out the the HashTable
        {
            HashedObj Element = hashentry.element;
            EntryType Info = hashentry.info;
            os << Element << " : " << Info << endl;
            return os;
        }
    };

    vector<HashEntry> array;
    int currentSize;

    bool isActive(int currentPos) const
    {
        return array[currentPos].info == ACTIVE;
    }
    int findPos(const HashedObj & x) const
    {
        int offset = 1;
        int currentPos = myhash(x);
        while(array[currentPos].info != EMPTY && array[currentPos].element != x)
        {
            currentPos += offset;
            offset +=2;
            if(currentPos >= array.size())
            {
                currentPos -= array.size();
            }
        }
        return currentPos;
    }
    void rehash()
    {
        vector<HashEntry> oldArray = array;
        array.resize(nextPrime(2*oldArray.size()));
        for(int j = 0; j < array.size(); j++)
            array[j].info = EMPTY;

        currentSize = 0;
        for(int i = 0; i < oldArray.size(); i++)
            if(oldArray[i].info == ACTIVE)
                insert(oldArray[i].element);
    }
    int myhash(const HashedObj & x) const
    {
        static thehash<HashedObj> hf;
        return hf( x ) % array.size( );
    }
};



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


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

    }


    return n;
}

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;
}

Symbol.h:

using namespace std;

class Symbol
{
private:
    int type;
    string data;
public:
    const string & getData() const
    {
        return data;
    }
    int getType() 
    {
        return type;
    }
    void setType(int Type)
    {   
        type = Type;
    }
    void setData(string Data)
    {
        data = Data;
    }
    bool operator== (const Symbol & rhs) const
    {
        return getData() == rhs.getData();
    }

    bool operator!= (const Symbol & rhs) const
    {
        return !(*this == rhs);
    }
    friend ostream & operator <<(ostream & outstream, Symbol & symbol) //overloaded to print out the the HashTable
    {
        int num = symbol.getType();
        string name = symbol.getData();
        outstream << name << " : " << num << endl;
        return outstream;
    }
};

和... Driver.cpp:

#include <iostream>
#include <iomanip>
#include <cassert>
#include <fstream>
#include <string>
#include <vector>
#include <time.h>
#include <unistd.h>
#include <map>
#include <cstdlib>
#include <cmath>
#include "LinearProbing.h"

using namespace std;

int TABLE_SIZE; //I know it's a global, but it allows the Table Size to be taken in within main() and used in hash()

size_t hasher(const string & key);


int main()
{
    Symbol temp;
    vector<Symbol> symbols;
    string s;

    int t;
    int hash_key_array[TABLE_SIZE]; //array to hold hash key values

    ifstream file;
    file.open("symbols.txt");
    cout << "Opening file..." << endl;
    usleep(1000000);

    if(!file)
    {
        cout << "System failed to open file.";
    }
    else
    {
        cout << "File successfully opened" << endl;
    }

    //for loop to read in the string name and the integer that follows the string name from symbols.txt
    while(file >> s)
    {
        temp.setData(s);
        file >> t;
        temp.setType(t);
        symbols.push_back(temp);
    }


    for(int i = 0; i < TABLE_SIZE; i++)
    {
        cout << symbols[i].getData() << "\n";
        cout << symbols[i].getType() << "\n";
    }


    cout << "What would you like the table size to be?" << endl;
    cin >> TABLE_SIZE;

    HashTable<Symbol> hashtable(TABLE_SIZE);
    cout << endl;

    for(int j = 0; j < TABLE_SIZE; j++)
    {
        temp.setData(symbols[j].getData());
        //cout << temp.getData() << endl;

        temp.setType(symbols[j].getType());
        //cout << temp.getType() << endl;

        cout << endl;

        hashtable.insert(temp);
    }
    hashtable.print();
}

size_t hasher(const string & key)
{
    size_t hashVal = 0;

    for(char ch : key)
    {
        hashVal = 37 * hashVal + ch;
    }
    return labs(hashVal % TABLE_SIZE);
}

1 个答案:

答案 0 :(得分:0)

: 0
: 1

行实际上代表:

  • 第一行:默认构造的Symbol对象,由Symbol operator<<打印。这是data的空字符串,后跟文字:,后跟0初始化type
  • 第二行:HashEntry的EMPTY的EntryType(整数值为1),由HashEntry << Info的{​​{1}}部分打印。

他们偶尔出现在输出中,因为operator<<打印所有分配HashTable::print(在这种情况下为HashEntry),而不仅仅是插入Driver中的那些。 CPP。