3

So, I decided to look back at some data structures to keep myself sharp ;)

I started to implement a hash table, when I remembered that I needed linked lists for the buckets so that I can avoid hash collisions. So I started my linked list...

I implemented all of the functional methods of my linked list class (add, get, remove, etc) and then I decided that I wanted to try something that I hadn't tried before. Overloading the array index operators so that my linked list indexes can be retrieved or assigned as if the linked list was an array.

I got the retrieval part working no problem:

template <class T>
T LinkedList<T>::operator[](const int &i) {
    return get(i);
}

The get function returns the data of the associated node, not the node itself...the setter should behave where the value supplied gets stored to the data attribute of node at the given index...my vision is that the user will not ever have to touch the ListNode class.

My end goal is that I can have a smart LinkedList that will behave like so:

LinkedList<int> list;

list[0] = 1;    //Allocates memory for 0th node and stores 1 as the data
list[3] = 2;    //Allocates memory for 1th,2th,and 3th nodes and sets 2 as the data
                //Unassigned nodes should use default constructors on data

int a = list[3];  //Sets a to 2
cout << list[0] << endl;  //prints 1

The getter works fine, but I am having trouble on the setter. Assume the set function with all index error checking and memory allocation is done, as it is. Any help would be appreciated. If it is impossible, then please let me know before I spend more time on it. Thanks.

jyore
  • 4,715
  • 2
  • 21
  • 26
  • Since the getter function must implemented as iteration, seems trivial to add the setter. However this interface will be clunky to use, I think. In your example above what is the expected `size` of the collision list? How do I (as a user) know that two items [1,2] are "empty"? How do plan to maintain associativity on removals, sine constant time removal is one of linked lists' main benefits? – Chad Oct 08 '11 at 04:35

2 Answers2

3

it looks like you want to return nodes by reference:

template <typename T>
class LinkedList {
...
  T& operator[](const size_t& i) { return this->get(i); }
  const T& operator[](const size_t& i) const { return this->get(i); }
...
};

(also assumes LinkedList::get() returns references)

justin
  • 104,054
  • 14
  • 179
  • 226
  • `const size_t& i` doesn't make much sense, as it is not needed. `size_t i` suffices. – Nawaz Oct 08 '11 at 04:55
  • @Nawaz const ref also suffices. it makes enough sense to me that it is *my* default, rather than by value. – justin Oct 08 '11 at 06:38
  • @Justin: I think it is overkill. Or you think it makes the call faster? – Nawaz Oct 08 '11 at 09:15
  • @Nawaz i do it that way because it's consistent with the rest of my code. – justin Oct 08 '11 at 09:24
  • @Nawaz passing arguments by const reference is the default convention in the c++ programs and libraries i write. if there's a good reason to deviate from the convention in a specific case, i do so. – justin Oct 08 '11 at 09:30
  • @Justin:The question it begs is why exactly *"passing arguments by const reference is the default convention in the c++ programs"*? – Nawaz Oct 08 '11 at 09:32
  • because i favor a consistent written style with few exceptions: "pass arguments by const reference, pass by reference if the argument is mutated. make exceptions if needed.", rather than other approaches, such as: "pass by value if they are builtin, and also *some* types if they are small and trivial to copy, *or* if a copy/mutation must occur in the implementation, *otherwise* by const reference... but mutable arguments shall be passed via pointer". the optimizer can still do its job. hope that helps... but why has this become so important? after all, the OP *also* passed by const reference. – justin Oct 08 '11 at 10:11
1

operator[] and get() should return a reference to the data.

template <class T>
T& LinkedList<T>::operator[](const int &i) {
    return get(i);
}
Pubby
  • 51,882
  • 13
  • 139
  • 180