I. Linked list node class
A linked List node class is best defined as a private inner class of a linked list class. However, since the code uses a template, there are a variety of compilation problems under VS2013, so it is defined externally instead.
template<class t>struct node{ T data; Node* prev; Node* next; Node (const t& src = T (), node* p = null, node* n = null): data (SRC), prev (p), next (n) {}
class LinkedList < T > ;};
Two. Iterator classes
Because of the traversal of the doubly linked list, the insert, the delete operation involves a large number of repetitive pointer operations. To improve code reusability, we introduce an iterator class.
Once an iterator is introduced, it is necessary to introduce two private sentinel nodes: Head and tail. Sentinel/sentry node. Recommendations are written as public internal classes. However, due to the fact that the syntax of the template is too harsh for the VS compilation environment, the expediency can only be changed to an external class
The role of head:
1. Easy to determine the empty and full list.
2. Simplify the operation of the linked list. It is primarily easy to get to the first element of the list, no matter how many times the first element undergoes a change. Second, it is convenient to control the termination condition of the iterator.
The role of Tail:
1. Easy to insert at the rear (this is also one of the differences between the doubly linked list and the unidirectional list: The unidirectional list can only be inserted after the current node, and the doubly linked list is best inserted before the current node).
2. When using an iterator, it is convenient to control the terminating condition of the forward traversal.
template<classT>classIterator<t>{ Public: Node<t>*Current ; LinkedList<t>*host; Public: Iterator<T> (node* C, linkedlist<t>*h): current (c), host (h) {}//solution references for iteratorst&operator* () { returnCurrent->data; } Constt&operator* ()Const { returnCurrent->data; } //the movement of iterators//Front + +iterator<t>&operator++() { current= current->Next; return* This; } //Post + +, for the code needs, this inside of the Post + + does not really move the iterator, just back peekIterator<t>operator++(int) {Auto I= Iterator<t> ( This->current->next, This-host); returni; } iterator<T>&operator--() { current= current->prev; return* This; } //does not move, just forward peekIterator<t>operator--(int) {Auto I= Iterator<t> ( This->current->prev, This-host); returni; } //Comparison of Iterators BOOL operator==(Constiterator<t>& src)Const { return(current = = Src.current && host = =src.host); } BOOL operator!=(Constiterator<t>& src)Const { return(Current! = Src.current | | | host! =src.host); } friendclassLinkedList < T > ;};
Three. List Type ADT
Template <classT>classlinkedlist{Private: intsz; Node<t>*Head; Node<t>*tail; voidInit ();//initialize head and tail; Public: Public: LinkedList (); LinkedList (Constlinkedlist&src); Virtual~LinkedList (); LinkedList&operator= (Constlinkedlist&src); Iterator<T>begin (); Iterator<T>end (); ConstIterator<t> begin ()Const; ConstIterator<t> End ()Const; intSize ()Const { returnsz; } BOOLIsEmpty ()Const { returnsz==0; } voidClear (); voidPushback (Constt&src); voidPushfront (Constt&src); voidPopback (); voidPopfront (); Iterator<T> Insert (iterator<t> it,Constt&src); Iterator<T> Remove (iterator<t>it); Iterator<T> Remove (iterator<t> from, iterator<t>to );};
Four. Begin () and end () operations
Template <classT>iterator<T> linkedlist<t>:: Begin () {returnIterator<t> (Head->next, This);} Template<classT>ConstIterator<t> Linkedlist<t>::begin ()Const { returnIterator<t> (Head->next, This);} Template<classT>iterator<T> linkedlist<t>:: End () {returnIterator<t> (Tail, This);} Template<classT>ConstIterator<t> Linkedlist<t>::end ()Const{ returnIterator<t> (Tail, This);}
Five. Insert
1. Insert the specified iterator position
Template <classT>iterator<T> Linkedlist<t>::insert (iterator<t> it,Constt&src) {Node<t>* p =it.current; ++sz; /** Return is a simplification of the following code * node* Myprev = p->prev;//The precursor of the node to be inserted * node* mynext = p; Successor of the node to be inserted * node* Mynode = new node (it, Myprev, Mynext); Apply for a new node and connect the precursor and successor * P->prev->next = Mynode; Let the precursor, the successor and oneself connect * P->prev = Mynode; */ returnIterator<t> (P->prev = P->prev->next =NewNode (SRC, P->prev, p), This); //The end result is to insert it in front of it.}
2. Insert in head or tail
Template <class t>void linkedlist<t>::p ushback (const t& src) { <class t>void linkedlist<t>::p ushfront (const t& src) { Insert (Begin (), SRC);}
Six. Delete Nodes
1. Delete the node at the specified iterator location
Template <classT>iterator<T> Linkedlist<t>::remove (iterator<t>it) {Node<t>* p =it.current; --sz; Iterator<T> result (P->next, This); P->prev->next = p->Next; P->next->prev = p->prev; Delete p; returnresult;} Template<classT>iterator<T> Linkedlist<t>::remove (iterator<t> from, iterator<t>To ) { if(sz==0)returnbegin (); for(Auto it = from; it!=to ;) It=Remove (it); returnto ;}
2. Other delete operations
Template <class t>void linkedlist<t>::p opback () { Remove (-- <class t>void linkedlist<t>::p opfront () { <class t> void linkedlist<t>:: Clear () { --End ());}
Seven. Memory management
Template <classT>LinkedList<T>:: LinkedList () {init ();} Template<classT>LinkedList<t>::linkedlist (Constlinkedlist&src) {init (); * This= src;//Call the overloaded operator=}template<classT>LinkedList<t>::~LinkedList () {clear (); Delete head; Delete tail;} Template<classT>LinkedList<T>& Linkedlist<t>::operator=(Constlinkedlist<t>&src) { if( This==&src) { return* This; } clear (); for(Iterator<t> it = Src.begin (); It!=src.end (); + +it) { This->pushback (*it); } return* This;} Template<classT>voidLinkedlist<t>:: Init () {sz=0; Head=NewNode (); Tail=NewNode (); Head->next =tail; Tail->prev =head;}
Doubly linked list