简体   繁体   中英

Dummy Head Node Linked List

I'm trying to write an insert function for string values for a circular doubly linked list. I saw that creating a dummy node is beneficial in doing this so I can eliminate special cases like when the list is empty. The problem is I'm not finding alot of good information on dummy head nodes. I understand their purpose, but I don't understand how I create/implement it.

appreciate all the code examples guys, tried to figure it out on my own getting a little stuck though if someone can look at it.

 #include <iostream>
 #include <string>
 using namespace std;
 typedef string ListItemType;

struct node {
node * next;
node * prev;
ListItemType value;

};
node * head;
node * dummyHead = new node;
void insert(const ListItemType input, node *  & within);

void main(){
     insert("bob",dummyHead);
}

void insert( const ListItemType input, node *  &ListHead){
   node *newPtr = new node;
   node *curr;
   newPtr->value = input;

curr = ListHead->next; //point to first node;
while (curr != ListHead && input < curr->value){
    curr = curr->next;
}
        //insert the new node pointed to by the newPTr before
        // the node pointed to by curr
    newPtr->next = curr;
    newPtr->prev = curr->prev;
    curr->prev = newPtr;
    newPtr->prev->next = newPtr;
}

For a circular doubly linked list, you can setup 1 sentinel node where both "next" and "prev" points to itself when list is empty. When list is not empty, sentinel->next points to first element and sentinel->prev points to last element. With this knowledge, your insert and remove function would look something like this.

This is very basic and your LinkedList and Node class maybe implemented differently. That is OK. The main thing is the insert() and remove() function implementation that shows how sentinel node(s) removes the need for checking for NULL values.

Hope this helps.

class DoublyLinkedList
{
    Node *sentinel;
    int size = 0;

    public DoublyLinkedList() {
        sentinel = new Node(null);
    }

    // Insert to the end of the list
    public void insert(Node *node) {
        // being the last node, point next to sentinel
        node->next = sentinel;

        // previous would be whatever sentinel->prev is pointing previously
        node->prev = sentinel->prev;

        // setup previous node->next to point to newly inserted node
        node->prev->next = node;

        // sentinel previous points to new current last node
        sentinel->prev = node;

        size++;
    }

    public Node* remove(int index) {
        if(index<0 || index>=size) throw new NoSuchElementException();

        Node *retval = sentinel->next;
        while(index!=0) {
            retval=retval->next;
            index--;
        }

        retval->prev->next = retval->next;
        retval->next->prev = retval->prev;
        size--;
        return retval;
    }
}

class Node 
{
    friend class DoublyLinkedList;
    string *value;
    Node *next;
    Node *prev;

    public Node(string *value) {
        this->value = value;
        next = this;
        prev = this;
    }

    public string* value() { return value; }
}

Why are you trying to use dummy node? I hope you can handle it without a dummy node. Eg:

void AddNode(Node node)
{
   if(ptrHead == NULL)
   {
       ptrHead = node;
   }else
   {
       Node* itr = ptrHead;
       for(int i=1; i<listSize; i++)
       {
            itr = itr->next;
       }
       itr->next = node;
   }
   listSize++;
}

The above one is an example to handle the linked list without dummy node.

For a circular double linked list without a dummy node, the first node previous pointer points to the last node, and the last node next pointer points to the first node. The list itself has a head pointer to first node and optionally a tail pointer to last node and/or a count.

With a dummy node, the first node previous pointer points to the dummy node and the last node next pointer points to the dummy node. The dummy nodes pointers can point to the dummy node itself or be null.

The HP / Microsoft STL list function uses a dummy node as a list head node with the next pointer used as a head pointer to the first real node, and the previous pointer used as a tail pointer to the last real node.

#include <iostream>
#include <string>
using namespace std;
typedef string ElementType;

struct Node
{
    Node(){}
    Node(ElementType element, Node* prev = NULL, Node* next = NULL):element(element){}
    ElementType element;
    Node* prev;
    Node* next;
};

class LinkList
{
public:
    LinkList()
    {
        head = tail = dummyHead = new Node("Dummy Head", NULL, NULL);
        dummyHead->next = dummyHead;
        dummyHead->prev = dummyHead;

        numberOfElement = 0;
    }

    void insert(ElementType element)
    {
        Node* temp = new Node(element, NULL, NULL);

        if (0 == numberOfElement)
        {
            head = tail = temp;
            head->prev = dummyHead;
            dummyHead->next = head;

            tail->next = dummyHead;
            dummyHead->prev = tail;
        }
        else
        {
            tail->next = temp;
            temp->prev = dummyHead->next;
            temp->next =  dummyHead;
            dummyHead->next = temp;
            tail = temp;
        }

        numberOfElement += 1;
    }

    int length() const { return numberOfElement; }
    bool empty() const { return head == dummyHead; }

    friend ostream& operator<< (ostream& out, const LinkList& List);
private:
    Node* head;
    Node* tail;
    Node* dummyHead;

    int numberOfElement;
};


ostream& operator<< (ostream& out, const LinkList& List)
{
    Node* current = List.head;
    while (current != List.dummyHead)
    {
        out<<current->element<<" ";
        current = current->next;
    }
    out<<endl;
    return out;
}
int main()
{
    string arr[] = {"one", "two", "three", "four", "five"};
    LinkList list;
    int len = sizeof(arr) / sizeof(arr[0]);
    for (int i = 0; i < len; ++i)
    {
        list.insert(arr[i]);
    }

    cout<<list<<endl;
}

I think this code can help you. When you want to implement some data structure, you must have a clear blueprint about it.

Do the following inside the constructor

ptrHead = new Node();
listSize = 1;

if you have tail also,

ptrHead->next = ptrTail;

The above code will create dummy node. Make sure you implementation should not affected by this dummy node.

eg:

int getSize()
{
   return listSize-1;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM