Doubly linked list implementation in C++
Unusual API

Some method names are a bit unusual in a linked list, here are some more common alternatives:


addToHead -> addFirst, unshift, prepend
addToTail -> add, addLast, append
removeFromHead -> removeFirst, shift
removeFromTail -> removeLast, pop
isInList -> contains


Information hiding

Users of DoublyLinkedList don't need to be aware of DoublyLinkedNode.
This implementation detail can be hidden.
I suggest to make it private by moving it out of the header file.

Naming

The naming is quite terrible at places. Here's the worst part:


DoublyLinkedNode(int nu, DoublyLinkedNode *ne = 0, DoublyLinkedNode *pre = 0) {
    info = nu;
    next = ne;
    prev = pre;
}



It would be better to call "ne" -> "next" and "pre" -> "prev", and "nu" -> "info" and use this-&gt; on the left hand sides:

DoublyLinkedNode(int info, DoublyLinkedNode *next = 0, DoublyLinkedNode *prev = 0) {
    this-&gt;info = info;
    this-&gt;next = next;
    this-&gt;prev = prep;
}


"info" is an unusual name for the payload in a linked list node.
"value" or "data" would be better.

Instead of DoublyLinkedNode, I'd call it simply Node.
As it can be private, and it's unlikely to need any other kind of node in the linked list implementation.

Constructor initialization

There's a simpler way of initializing variables in the constructor:

DoublyLinkedNode(int info, DoublyLinkedNode *next = 0, DoublyLinkedNode *prev = 0) : info(info), next(next), prev(prev) {}


Use nullptr

Instead of setting pointers to 0 to null them out,
it's recommended to use nullptr.
You might need to enable this in your compiler,
for example with g++ you can pass the --std=c++0x flag.

Avoid external references when you don't really need them

This loop in the destructor makes references to head and isEmpty defined elsewhere:

for (DoublyLinkedNode *p; !isEmpty();) {
    p = head-&gt;next;
    delete head;
    head = p;
}


It would be more clear and simple to avoid such external references:

for (DoublyLinkedNode * node = head; node != nullptr;) {
    DoublyLinkedNode * toDelete = node;
    node = node-&gt;next;
    std::cout &lt;&lt; "deleting: " &lt;&lt; toDelete-&gt;info &lt;&lt; "\n";
    delete toDelete;
}


For loop without body

The for loop in this method doesn't have a body.
This is not recommended.


bool DoublyLinkedList::isInList(int el) const {
    DoublyLinkedNode *tmp;
    for (tmp = head; tmp != 0 &amp;&amp; !(tmp-&gt;info == el); tmp = tmp-&gt;next);
    return tmp != 0;
}



The reason the loop doesn't have a body is because of the !(tmp-&gt;info == el) in the loop condition.
That condition doesn't belong there.
It's recommended to put in the loop condition only what concerns the iteration process, in this example checking if the loop variable tmp has reached the end of the list or not.

The condition !(tmp-&gt;info == el) is about something else,
it's about evaluating the return value of the function.
That condition would be much better in the loop body, like this:

bool DoublyLinkedList::isInList(int el) const {
    for (DoublyLinkedNode * node = head; node != nullptr; node = node-&gt;next) {
        if (node-&gt;info == el) {
            return true;
        }
    }
    return false;
}


Also note that this alternative also saves an extra boolean check.