0

I wanted to implement linear probing for hashtabe in c++,but the key,value pair would be of generic type like: vector< pair< key,value> >(where key,value is of generic type).

Now,in linear probing if a cell is occupied we traverse the vector until we find an empty cell and then place the new pair in that cell.

The problem is,that in generic type,how would I be able to check if a particular cell is occupied or not? I cannot use these conditions:

if(key == '\0')//As key is not of type string 

OR

if(key == 0)//As key is not of type int

So,how will be able to check if a paricular cell in the vector is empty or not? Please correct me if I misunderstood the concept.

Saurabh
  • 60
  • 12

3 Answers3

2

I think you can just check if the element of the vector has meaningful key and value:

if(vector[i] == std::pair<key, value>())
    //empty

or, if you only care about the keys

if(vector[i].first == key())
    //empty

This approach assumes that the default constructor of key type constructs an object that would be considered an "empty" or "invalid" key.

SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105
  • What happens if `key` or `value` doesn't have a default value? An `int` for example? – Fatih BAKIR Oct 10 '16 at 08:26
  • 1
    @FatihBAKIR, why wouldn't they? An int would be initialized with 0 in this case. Of course this approach assumes that the default constructor of `key` type creates an object which is considered an `empty` or `invalid` key. Edited the answer to emphasize that. – SingerOfTheFall Oct 10 '16 at 08:28
  • @SingerOfTheFall,should I make an empty pair(in the constructor) for each index of the vector?Wouldn't this put a constraint that the size of the vector should be known beforehand. – Saurabh Oct 10 '16 at 12:11
  • @Saurabh, not necessarily. You just need to make sure that when an element in a vector is removed, you either 1) really delete it from the vector, or 2) replace is with an empty pair. This way when you traverse the vector later, you will either find an empty pair somewhere and use that cell, _or_ reach the end of the vector, and append to it. – SingerOfTheFall Oct 10 '16 at 12:13
  • @SingerOfTheFall,just one thing more.I wrote some code accordingly,please see the link: (https://gist.github.com/Sharma96/f312af6b3219c992dd1519a572dfddf3) .There is a weird thing happening in the code,if you will run the code,you will find that when the value of y(in ch function) is 5,it is printing 135057 for the value v[y].first,how is it initializing the value for the pair at the 5th index(and only the 5th index),while I am calling the add function 4 times only. – Saurabh Oct 10 '16 at 12:59
  • @Saurabh, you are accessing out-of-bounds index (your vector only has 4 items, and in `ch()` you are accessing more), this is undefined behaviour. – SingerOfTheFall Oct 10 '16 at 13:15
  • Thank you for checking the code.But,then how come it is printing some arbitrary value only for the 5th index and 0 for 6,7,8,9 indexes? – Saurabh Oct 10 '16 at 17:03
  • @Saurabh you are accessing memory that doesn't belong to you. You can get anything there. It can be 0, it can be trash, it can be some meaningful data, or your may just get a set fault and crash. – SingerOfTheFall Oct 10 '16 at 17:06
0

You could use a free function isEmpty for checking if a key type is empty. Define a templated default function that works for most types, and make special functions that cannot be handled by the default.

E.g.

template<typename T>
bool isEmpty(const T &t) {
    return !t;
}

bool isEmpty(const std::string &s) {
   return s.length() == 0;
}

bool isEmpty(double d) {
    return d < 0;
}

isEmpty(0); // true
isEmpty(1); // false
isEmpty(std::string()); // true
isEmpty(std::string("not empty")); // false
isEmpty(1.0); // false
isEmpty(-1.0); // true

You only need to specialize for key types that do not have an operator ! or where a different logic is needed for the check

king_nak
  • 11,313
  • 33
  • 58
0

In case you don't want to rule out the possibility to have "default constructed" elements in your hash you can build a parallel data structure, like a std::bitset (if you know in advance the maximum size of your data structure) or a std::vector<bool>, that in the following i will call has. has[i] will be true if vector[i] contains a valid, actually inserted element.

So the operations should be modified as follows:

  • insert: go on scanning the vector until you find a position i such that has[i] == false
  • remove element in position i: set has[i] to false

Hope this helps