Hi, everyone. I'm working on a hash table program, but while I run it, the windows just ended with "Process exited after 2.92 seconds with return value 3221225477" without showing the correct result. I can't find what's wrong with my code.
Thanks a LOT for your help!!
//HashTable ver3.h
#ifndef HASHTABLE ver3_H
#define HASHTABLE ver3_H
#include<vector>
#include"string.h"
usingnamespace std;
class Table_Items
{
public:
string key, gender;
int height, weight;
//Default constructor
Table_Items();
//Constructor
Table_Items(string, string, int, int);
//return gender by item
string getGender();
//return height by item
int getHeight();
//return weight by item
int getWeight();
};
class HashTable
{
public:
//Hash function using quadratic probing
int QuadraticProbing(string key, int i);
public:
//Default constructor
HashTable();
//Destructor
~HashTable();
//add data into your hash table
void addItem(string key, string gender, int height, int weight);
//return gender by item
//string getGender();
//return height by item
//int getHeight();
//return weight by item
//int getWeight();
//return item by selected key
Table_Items & operator [] (string key);
private:
//Number of slots in table
staticconstint table_size = 10000;
Table_Items patients_data[table_size];
// Will hold table_arr status
// (0 for Empty, 1 for there is data, -1 for deleted)
int status_arr[table_size];
//Number of elements stored in table
int count = 0;
};
#endif
I've added the above code in it, and the result is :
"File successfully open
--------------------------------
Process exited after 2.389 seconds with return value 3221225477"
I've just found a problem, which is in the function addItem, I should add this status_arr[j] = 1;
before return
Hence, the result will become :
Hash Table Overflow !
hashtable["0015239667"].getGender(): female
hashtable["0015239667"].getHeight(): 160
hashtable["0015239667"].getWeight(): 57
--------------------------------
Process exited after 2.583 seconds with return value 3221225477
I also suspect the hash table copy, made for the function EvaluateFunc, is bad. I suspect the copy is not being made properly; you have not provided a constructor to do it so you get the default copy constructor.
If EvaluateFunc received the hash table by reference, the copy would not be necessary: void EvaluateFunc(HashTable& hashtable, vector<string> testCases)
1. Compile with maximum warnings and pay attention.
1 2 3 4 5 6 7 8 9 10 11
$ g++ -g -Wall -Wextra -std=c++11 foo.cpp
foo.cpp:90:33: warning: unused parameter ‘Key’ [-Wunused-parameter]
Table_Items::Table_Items(string Key, string Gender, int Height, int Weight)
^
foo.cpp:90:45: warning: unused parameter ‘Gender’ [-Wunused-parameter]
Table_Items::Table_Items(string Key, string Gender, int Height, int Weight)
^
foo.cpp: In member function ‘Table_Items& HashTable::operator[](std::__cxx11::string)’:
foo.cpp:194:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
Yes, that "control reaches end of non-void function" is a doozy, as pointed out by Repeater earlier.
2. Run a simple test case in the debugger - again, listen to Repeater.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
$ gdb -q ./a.out
Reading symbols from ./a.out...done.
(gdb) run
Starting program: ./a.out
1000
Program received signal SIGSEGV, Segmentation fault.
0x00000000004017c0 in Table_Items::getHeight (this=0x0) at foo.cpp:172
172 return height;
(gdb) bt
#0 0x00000000004017c0 in Table_Items::getHeight (this=0x0) at foo.cpp:172
#1 0x00000000004019fa in main () at foo.cpp:202
(gdb) up
#1 0x00000000004019fa in main () at foo.cpp:202
202 cout << hashtable["Z"].getHeight() << endl;
(gdb)
SIGSEGV in Linux == STATUS_ACCESS_VIOLATION in Windows.
LOOK at the value of 'this' in your function. No valid this is ever NULL.
And the culprit? A lookup of a non-existent entry.
Just for the sake of stating the law of C++ clearly; if your operator[] claims to return a Table_Items object, it MUST return one. You MUST come up with some sensible way of handling the case where a non-existent entry is requested.
While we're on the subject of how long it takes, I note that while the insertion is done by hashing the key to find the insertion location, the lookup is not done by hashing the key to find where to start looking; the lookup simply walks over the entire table from start to end, until it finds what its looking for. In the worst case, when the key is not present, the lookup examines every element in the table.
Well that would do it. I didn't look at wall of code, just his output and his orig post which indicated a desire for speed. Which I am not sure he read, looking at it.. string processing is adding no speed..
A hash table solution is supposed to do this:
insert:
data-> key
table[key] = data;
and searching:
data = table[key]; //NO ITERATION HERE
where you may or may not need to handle collisions (2 datas, same key).
To deal with hash collisions, you look for an empty slot in the hash table. Your table has 10000 buckets and you're inserting 10,000 items. As the table fills up, you have to search longer and longer distances to find an empty slot. I'm not certain, but I suspect this makes your insertion O(n2)
And as Repeater points out, your lookup is linear, so that's definitely O(n) and looking up all n items takes O(n2) time.
So you're doing 2 things that require O(n2) time with n=10000, so that's O(100,000,000) operations for each. Add to that the fact that so many parameters are being passed by value and you've got a slow moving program.
The point of a hash table is that the hash value should quickly lead you to the item. Choosing the next empty hash bucket to resolve collisions is okay, but only if the number of hash buckets is large compared to the number of items in the table. Otherwise it's more common for each bucket to contain a linked list of items.
So I think you should decide how you want to resolve collisions. Then we can help you fix the other issues.