-2

I am working on a project for my University where i have to implement a Hash table. I am quite new to c++, so please forgive me if I am not specific enough or if I have completely wrong assumptions.

Soo..my main problem is that I have a so called "Bucket" which is a struct in my program and which contains a pointer array of N(template parameter) places.

struct Bucket {
    T *kptr{ nullptr };
    Bucket *bptr{ nullptr }; //For overflow chains (linear Hashing)
    Bucket(Bucket *bptr = nullptr) : kptr(new value_type[N]),bptr(bptr) {}
    ~Bucket() { if(bptr) delete[] bptr; if (kptr) delete[] kptr; }
};

In my main Class named My_Set for example I have an additional Bucket *table of [1<

My first assumption was to initialize the kptr array to nullptr and then in the insert method to make something like

void insert(Bucket &bkt, T &key) {
    for (int i=0; i<N, ++i) {
        if (bkt.kptr[i]) { //Check on nullptr!
           kptr[i] = key; 
        }
    }
}

But that´s not possible because then kptr should be Bucket T **kptr and not Bucket *kptr as far as i understood it. So, is there any other efficient way to check one single field of an array if it has been assigned to an Object already or not?

IMPORTANT: I am not allowed to use STL Containers, Smart Poitners and similar things which would make the whole thing much easier. Thanks!

  • 1
    Dont use new and delete, use std::array instead. It makes your code more readable, more resistant to bugs and easier to debug. Also for a table i'd always prefer dimX*dimY 1 dimensional array over a 2 dimensional. Edit: sorry for not reading Important note ;) – lars May 23 '17 at 15:22
  • 3
    `kptr` should be a `T **`. It should be allocated, to a sufficient size, in the constructor and cleared. Then it's trivial to check if one of the array's members is a `nullptr`. – Sam Varshavchik May 23 '17 at 15:22
  • 1
    @lars: See the **IMPORTANT** note at the bottom of the post. I'm sure `std::array` is included in that. Sad, but some some teachers insist on teaching the hard way before (or even instead of) the right way. – Fred Larson May 23 '17 at 15:23
  • 1
    @StefanPadu: Please edit the question. Don't put corrections in comments. – Fred Larson May 23 '17 at 15:25
  • 1
    If ``N`` is a template parameter (thus known at compile time), why not make ``kptr`` of type ``T* kptr[N]`` ? It would remove a level of dynamic allocation. – nefas May 23 '17 at 15:26
  • @SamVarshavchik that's what I actually said after my "insert" Method....but as far as I heard, it is very unefficient to do so?!? Additionally, what do you mean with allocate and then clear? How would that look like in the syntax? – Stefan Padu May 23 '17 at 15:27
  • @nefas - because that would make an array on the stack! I need to allocate the space on the Heap with "new" command – Stefan Padu May 23 '17 at 15:28
  • Is there a reason (constraint from the exercise ...) for that ? BTW ``new`` is an operator, not a command. – nefas May 23 '17 at 15:31
  • 1
    Issues of efficiencies typically are dealt with once one has sufficient knowledge and expertise in C++. Notions of efficiency is less critical when one's primary goal appears to be to learn the language, and how it works. So you do not need to worry about efficiency, at this time. As far as how to allocate and clear the initial contents of a dynamically-scoped array, you will find a detailed explanation in your C++ book; a much better explanation than a brief comment on stackoverflow.com can provide. stackoverflow.com does not work well as a tutorial site. PS: Your last edit was utterly wrong. – Sam Varshavchik May 23 '17 at 15:32
  • @nefas Maybe they want to see if we really understood the basic concepts of c++. Using smart poitners and STL Containers would eventually give us the opportunity to solve this without understanding them completely. Additionally, actually this Hashtable is an Container - i have to implement alls the iterators and methods which an STL Container offers - so it would not be purposeful to implement an Container using STL Containers. – Stefan Padu May 23 '17 at 15:37
  • My question was more "is there a constraint in the exercise that says 'use ``T**``'" or is it just you who want to use ``T**`` ? – nefas May 23 '17 at 15:42
  • @nefas...sorry my englisch is not the best. So there isn´t any constraint. Actually I wanted to use T** (because i think that would be the only possibility to check on nullptr). But even the prof said that would be an unefficient method to check if filled or not. So actually that´s why i was asking if there is any other possibilty to check if field has been filled? – Stefan Padu May 23 '17 at 15:45
  • @SamVarshavchik i do not want any tutorial! My only question is how can a pointer array be checked whether a field is filled or not except the T ** on nullptr checking. – Stefan Padu May 23 '17 at 15:47
  • 1
    @StefanPadu so, if your professor told you that it is inefficient to check whether the pointers have been assigned, then why do you ask how to check whether the pointers have been assigned? :) – eerorika May 23 '17 at 15:54
  • as long as you can, avoid raw pointers ! Here you can (and should) use a static array. – nefas May 23 '17 at 16:02
  • @nefas thanks, but I am sure that we are not allowed to use them. I will ask him again why he ment that the T ** on nullptr solution is inefficient because i did not get an specification for his statement. The only alternative which comes to my mind now is a counter in Bucket which counts the fields which have already been assigned (because filling is alway executed from the beginning to the end) – Stefan Padu May 23 '17 at 16:14
  • 1
    "how can a pointer array be checked whether a field is filled or not except the T ** on nullptr checking" every word in there is valid English; unfortunately as a whole this makes no sense. From the other comments, it looks like your professor expects you to implement your homework assignment in a certain, specific way. You are unable to effectively explain the exact details, but expect everyone else to guess how, and tell you how to do it. The best thing for you to do, it seems, is to ask your prof. for help with your questions; that's what your prof. is being paid for, after all. – Sam Varshavchik May 23 '17 at 16:16
  • By static array I meant ``T[]``. I hope you are allowed to used ``T[]``. – nefas May 23 '17 at 16:19
  • @SamVarshavchik thanks Sam for your english lessons! I guess everybody understood whats all about - no need of getting angry or rude at all! Moreover you are not forced to comment if you still don't understand ;) – Stefan Padu May 23 '17 at 16:30
  • @nefas T[] is allowed ! – Stefan Padu May 23 '17 at 16:53

1 Answers1

0

Check whether pointer in pointer array is already “filled”

... So, is there any other efficient way to check one single field of an array if it has been assigned to an Object already or not?

Yes: Initialize the pointer to nullptr. Then, if the pointer has a value other than nullptr, you know that it has been pointed to an object.

However, your professor is correct that your checking is inefficient. On every insert you iterate through all previously inserted objects.

That is unnecessary. You can avoid trying to check whether any of the pointers have been assigned by remembering where the next free pointer is. How can we "remember" things in algorithms? Answer: Using variables. Since you must remember for each instance of your container, you need a member variable.

Since you are using this new variable to remember the next free pointer, how about we name it next_free. Now, considering that the variable must refer to an existing object, what type should it have? A reference would be a good guess, but you must also be able to reassign it once an element is inserted. What can refer to an object like a reference, but can be reassigned? Answer: A pointer. Since this pointer is going to point to a pointer to T, what should be its type? Answer: T**. What should it be initialized to? Answer: The address of the first element of kptr. With such member, insert can be implemented like this:

void insert(T &key) { // why would there be a Bucket argument for insert?
    *next_free++ = new T(key); // Note: Do not do this in actual programs. Use
                               // RAII containers from the standard library instead
}

then kptr should be Bucket T **kptr and not Bucket *kptr as far as i understood it.

Correct. A T* can not point to an array that contains pointers (unless T happens to be a pointer) - it can point to an array of T objects. A T** can point to an array of pointers to T.

Instead of pointers to separately allocated objects, it would be more efficient to use a flat resizable array. But since you are not allowed to use std::vector, you would then have another standard container to re-implement. So consider whether the efficiency is worth the extra work.

Community
  • 1
  • 1
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • well, thats exactly what I was trying to do...but how can this be done? As far as i know, like i actually mentioned in my request, I would have to make a T ** kptr instead of T *kptr - but my prof told me this is an unefficient way to do so?! – Stefan Padu May 23 '17 at 15:31
  • OK. Is the "unefficiency" a problem? – eerorika May 23 '17 at 15:33
  • Unfortunately yes :/ But anyway, i think i will just do so, because i can´t imagine that there is any other "more efficient" way to do so ! Making an enum State {free, inuse} is much more unefficient i guess ... – Stefan Padu May 23 '17 at 15:57
  • Thanks a lot!! That looks quite good already! But i need the Bucket& as a parameter since my Table consists of more Buckets (See initial post where i was talking about the Bucket *table in my main class). – Stefan Padu May 23 '17 at 16:40
  • It might also be worth making sure that `next_free` points to an actual element of `kptr`, so you don't flow off the end of the array. – Justin Time - Reinstate Monica May 23 '17 at 18:31
  • @JustinTime how can i check this? You mean to check if it points to an object of type T or just check if it has already passed the bucketsize? – Stefan Padu May 24 '17 at 10:22
  • 1
    @StefanPadu The array has limited size (`N`). Justin Time is suggesting that you could check whether the caller of insert tries to insert more than `N` elements. You'll find the number of inserted elements by subtracting `kptr` from `next_free`. – eerorika May 24 '17 at 10:41
  • @user2079303 well, ok thanks! Just one question left for you :D *next_free++ = new T(key); shouldn't it be **next_free++ = key ....since T array is allocated in Bucket constructor and nextFree is a T **? – Stefan Padu May 24 '17 at 10:58