A doubly linked list without sentinel nodes is a generic doubly linked list, with a head pointer pointing to the first node, each node having a key value and two pointers next and pre, pointing to the adjacent nodes, the pre=null of the head node, the next=null of the tail nodes, and more clearly, But there are also problems: in the search and deletion of nodes and other operations, it is unavoidable to judge the boundary conditions, such as node==null. Let's take a look at the code for this list:
/* * To implement a doubly linked list without sentinel nodes, you need to judge the boundary condition by yourself */#include <iostream>using namespace std;class list {struct node {int key;node* next;n ode* pre;node (int k): Key (k), Next (null), pre (NULL) {}};p ublic:node* head;int len;list (): Head (NULL), Len (0) {}~list () {No de* TMP1 = head, *tmp2;while (tmp1! = NULL) {tmp2 = Tmp1->next;delete tmp1;len--;cout << "len=" << Len < < ENDL;TMP1 = TMP2;}} /* * Insert node at head */void inserthead (int k) {node* n = new node (k); n->next = Head;head = N;if (n->next! = NULL) {N->nex T->pre = n;} len++;} /* * Delete the node pointed to by the pointer */int del (node* N) {if (n = = NULL) {return-1;} if (n->pre! = NULL) {n->pre->next = N->next;} else {head = N->next;} if (n->next! = NULL) {n->next->pre = N->pre;} Delete N;len--;return N->key;} /* * Find node with a key value */node* searchlist (int k) {if (len = = 0) {return NULL;} node* tmp = Head;while (tmp! = NULL) {if (Tmp->key = = k) {break;} TMP = Tmp->next;} return TMP;} /* * Traverse list */void travellist () {node* tmp = Head;while (TMP = NULL) {cout << tmp->key << "; tmp = Tmp->next;} cout << Endl;}}; int main () {list* L = new list (); L->inserthead (5); L->inserthead (4); L->inserthead (3); l->travellist (); l >del (L->head->next); L->travellist ();d elete L;return 0;}
each time the boundary condition is judged, it does not increase the complexity of the time fundamentally, but it has an effect on its constant term, which can be omitted if a two-way circular linked list with Sentinel nodes is used. We use a "dumb" nil node to replace the previous head head pointer, the NIL node key value has no actual meaning, mainly focus on its next and pre, initially, the list only a NIL node, Nil.next point to themselves, Nil.pre also point to themselves. When several nodes have been added, Nil.next points to the head node, while nil.pre points to the tail node, and similarly, the pre of the head node is no longer null but points to nil, and next to the tail node is no longer null, it also points to nil.
The advantage of this is that when we judge the boundary conditions, we do not need to judge whether it is empty, especially when the node is deleted, only two sentences can be written. However, this also brings some problems, that is, to allocate extra space to store the nil node, if for more than a short list, this may be a large amount of redundant space code.
The code is as follows:
/* * Implement band Sentinel is a two-way loop linked list */#include <iostream>using namespace std;class list {struct node {int key;node* next;node* Pre;nod E (int k): Key (k), Next (null), pre (NULL) {}};//node* head;public:node* nil; Sentinel node int len;list (): Nil (), Len (0) {nil = new node (0);//Initialize sentinel node//Let list loop up Nil->next = Nil;nil->pre = nil;} ~list () {//To delete the node if it is still present in the list if (len = = 0) {delete Nil;return;} node* N1 = nil->next;node* N2 = null;while (n1! = NULL && N1! = nil) {N2 = N1->next;delete n1;len--;n1 = n2; }delete Nil;} /* * In the head Insert node */void inserthead (int k) {node* n = new node (k); n->next = Nil->next;n->pre = Nil;nil->next = n;// Don't lose this sentence n->next->pre = n;len++;} /* Delete node, here to delete the operation only need to write two sentences, than the list operation without Sentinel to concise multi */void del (node* n) {n->pre->next = N->next;n->next->pre = n-> Pre;delete n;len--;} node* searchlist (int k) {node* tmp = nil->next;//let nil's key value never be equal to K//nil->key = k + 1;//while (tmp->key! = k) {WHI LE (tmp! = Nil && Tmp->key! = k) {tmp = Tmp->next;}if (tmp! = nil) {return tmp;} else {return NULL;}} /* * Traverse list */void travelclockwise () {node* TMP = nil->next;while (tmp! = nil) from next pointer direction {cout << tmp->key <&L T "; tmp = Tmp->next;} cout << Endl;} /* * Traverse list */void travelanticlockwise () {node* TMP = nil->pre;while (tmp! = nil) from the pre pointer direction {cout << Tmp->key < < "; tmp = Tmp->pre;} cout << Endl;}}; int main () {list* L = new list (); L->inserthead (5); L->inserthead (4); L->inserthead (3); L->travelclockwise () ; L->del (L->nil->pre);//l->travelclockwise (); L->travelanticlockwise (); return 0;}
Introduction to the Algorithm IX (10.2 without Sentinel node and two-way linked list with sentinel node)