2

I am writing my own implementation of a doubly linked list for school assignment and I use an inner node class called Node inside the list class, which represents list nodes that are linked to each other (as is usually the case with linked lists).

class DoublyLinkedList<T>
{
    class Node
    {
        T obj;
    }
}

I wonder, for large lists with many nodes, since each Node object may refer to an instance of the parent list class, is it a significant overhead and suboptimal design? It surely is convenient to have as a non-static class - then the nodes may alter parent lists first and last references, which I have found to be great for incapsulation.

If I make Node static, it can no longer (without explicit member reference to the list) be used to manipulate the parent lists first and last and I have to approach it all from the other way around - the list will assign and manipulate nodes through its own methods, that is link them to each other, unlink and naturally adjust its first and last values.

For the sake of good design and learning, I would like to know what is The Smart Thing To Do (c) (if any)?

Armen Michaeli
  • 8,625
  • 8
  • 58
  • 95

2 Answers2

4

If the inner class is not static then an implicit reference to the parent class already exists and you can refer to it through DoublyLinkedList.this from inside Node class.

In any case I don't see why a Node class should be able to modify directly attributes of its parent class. Methods that alter the list (so first and last too) should be of DoubleLinkedList class and not directly of Node class. This exactly for encapsulation, a Node instance shouldn't know anything about where it is contained or how it is used from the outside.

Jack
  • 131,802
  • 30
  • 241
  • 343
  • thank you. This is not my first doubly linked list implementation. I used to do it the way you suggested, but for some funny reason thought it'd be worth a try. I refactored it for a static Node class now. – Armen Michaeli Mar 09 '13 at 14:45
  • I don't see the point of making it `static`. If you accept that your `Node` class uses references to the list instance then both classes are tightly coupled: a `Node` instance doesn't make any sense without its parent class (since it uses references to it) so there's no point in allowing to be instanced without an enclosing instance of `DoublyLinkedList`. If you make it `static` you allow by design to instantate it whenever you want which breaks the whole behavior. – Jack Mar 09 '13 at 15:11
  • Well, for me the overhead is decisive factor, and it was simply for convenience that I had the class as non-static. I made it static, which solved the unneeded overhead problem, and moved the methods that refer to the list out of the node class into the list class itself. In most ways, I haven't lost anything but gained the size and speed advantage. The coupling between classes is now also more loose, and the code is more portable (not that it matters much in my case) because not all OOP languages support non-static classes. – Armen Michaeli Mar 10 '13 at 10:52
  • Moving the methods outside the inner class is the best choice indeed. But with a non static class you would had the reference to the parent already available through `DoublyLinkedList.this` so there wouldn't have been any overhead. You wouldn't have to store any local variable in the inner class to access the containing one. – Jack Mar 10 '13 at 13:47
2

The overhead would be exactly one reference per node. Assuming that the node in addition to the payload also has a prior link and a back link, the overhead for an extra reference to the parent would amount to about 33% in additional memory use (1 reference on top of 3 existing ones). This is considerable overhead, especially for large node counts and small payloads. On the other hand, with larger payloads it would not matter much.

In general, though, I would not make an assumption about the payload size, and make the Node class static.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523