The operating characteristics of the doubly linked list:
(1) "inquiry" and the same as the single linked list;
(2) "Insert" and "delete" need to modify the pointer in two directions at the same time.
However, for a two-way loop, the list is inserted very quickly at the end of the table, with an O (1) time, because there is a pointer to the front, so the two-way loop list is easy to find the element at the end of the table, so the two-way circular list comparison is suitable for frequent insertion at the end of the case.
Empty linked list:
Two-way cyclic linked list node construction:
Class Doublelistnode{private: Type data; Doublelistnode *prev; Forward pointer field Doublelistnode *next; latter pointer field};
Because it needs to be used for the doublelist class , it needs to be transformed as follows :
Template <typename type>class doublelistnode{ //friend declaration friend Class doublelist<type>; Friend Class listiterator<type>; Template <typename t> friend Ostream &operator<< (ostream &os, const doublelist<t> & List);p rivate: doublelistnode (const Type &datavalue) :d ata (datavalue), prev (null), Next (null) {} Type data; Doublelistnode *prev; Forward pointer field Doublelistnode *next; latter pointer field};
Two-way cyclic linked list construction :
Template <typename type>class doublelist{ friend class listiterator<type>; Template <typename t> friend Ostream &operator<< (ostream &os, const doublelist<t> & List);p ublic: doublelist (); ~doublelist (); void push_back (const Type &data); void Push_front (const Type &data); void Insert (int position, const Type &data); void Pop_front (); void Pop_back (); void Remove (const Type &removedata); BOOL Search (const Type &searchdata) const; BOOL IsEmpty () const { return (First->next = = first); } Private: //Insert node X into node previous after void Insertprivate (doublelistnode<type> *previous, Doublelistnode<type> *x); void Removeprivate (doublelistnode<type> *x);p rivate: doublelistnode<type> *first;};
construction and destruction of linked list :
Construct the list template <typename type>doublelist<type>::D oublelist () {First = new Doublelistnode<type > (0); First->next = First; First->prev = First;}
destructor list template <typename type>doublelist<type>::~doublelist () { doublelistnode<type> * Deletenode = NULL; Save chain footer Element doublelistnode<type> *tmp = first; First it points first to the real element, firstly = first->next; All the way to the end of the list while (first! = tmp) { deletenode = first; First = next; Delete deletenode; } Releases the empty node (header) of the linked list delete tmp;
Two main forces for inserting and deleting linked list elements :
Same as Private member//Insert node template <typename type>void doublelist<type>::insertprivate (doublelistnode< Type> *previous, doublelistnode<type> *x) { X->prev = previous; X->next = previous->next; Previous->next->prev = x; Previous->next = x;}
Delete node template <typename type>void doublelist<type>::removeprivate (doublelistnode<type> *x) { if (x = = first) throw Std::range_error ("Permission denied to delete first pointer"); X->prev->next = x->next; X->next->prev = x->prev; Delete x;}
Insert for customer :
Insert to Footer template <typename type>void doublelist<type>::p ush_back (const Type &data) {Doublelistnode <Type> *newnode = new doublelistnode<type> (data); Find the previous node of first doublelistnode<type> *previous = first->prev; Insert Insertprivate (Previous, newNode);} Insert into table header template <typename type>void doublelist<type>::p ush_front (const Type &data) {Doublelistnode <Type> *newnode = new doublelistnode<type> (data); Inserted after first insertprivate (first, newNode);} Insert to any position (specified by position) template <typename type>void doublelist<type>::insert (int position, const TYPE &data) {if (position = = 1) return Push_front (data); int count = 1; Previous represents a position before the insertion position doublelistnode<type> *previous = first->next; If the position is too large, then previous find first will stop//the element should be inserted at the end of the list while (Count < position-1 && Previous! = first) {+ + count; Previous = previous->next;}//If the end of the linked list is found or if the linked list is empty at this time, insert to footer if (previous = = first) return push_back (data); If a suitable insertion position is found doublelistnode<type> *newnode = new doublelistnode<type> (data); Insertprivate (Previous, newNode);}
Delete provided to the customer :
Delete Footer element template <typename type>void doublelist<type>::p op_back () { removeprivate (first->prev);} Delete Table header element template <typename type>void doublelist<type>::p Op_front () { removeprivate (first->next) ;} Delete all elements of element value Removedata template <typename type>void doublelist<type>::remove (const Type &removedata { if (IsEmpty ()) throw std::range_error ("link list is empty"); for (doublelistnode<type> *searchnode = first->next; Searchnode! = First; Searchnode = Searchnode->next) { if (Searchnode->data = = removedata) removeprivate (Searchnode) ; }}
To see if it exists in the linked list :
Template <typename type>bool doublelist<type>::search (const Type &searchdata) const{ doublelistnode<type> *searchnode = first->next; while (searchnode! = first) { if (Searchnode->data = = Searchdata) return true; Searchnode = searchnode->next; } return false;}
All elements of the output list ( for testing purposes ):
Template <typename type>ostream &operator<< (ostream &os, const doublelist<type> &list) { For (doublelistnode<type> *currentnode = (list.first)->next; CurrentNode! = List.first; CurrentNode = currentnode->next) os << currentnode->data << "; return OS;}
design and implementation of bidirectional loop-linked list iterator :
In addition to adding operator--, hardly made any changes to the template <typename type>class listiterator{public:listiterator (const doublelist <Type> &_list): List (_list), CurrentNode ((_list.first)->next) {}//reload *operator const TYP e &operator* () const throw (Std::out_of_range); Type &operator* () throw (Std::out_of_range); Overload->operator Const doublelistnode<type> *operator-> () const throw (Std::out_of_range); Doublelistnode<type> *operator-> () throw (Std::out_of_range); Overload ++operator Listiterator &operator++ () throw (Std::out_of_range); Note: The value returned here is not reference listiterator operator++ (int) throw (std::out_of_range); Overload--operator,//actually this version of the--operator is imperfect,//because he did not make any mistakes in controlling listiterator &operator--(); Note: The value returned here is not reference listiterator operator--(int); BOOL IsEmpty () const {return (CurrentNode = = List.first); }private:const doublelist<type> &list; DoublelistNode<type> *currentnode;};
template <typename type>const Type &listiterator<type>::operator* () Constthrow (Std::out_of_range) {if ( IsEmpty ()) Throw Std::out_of_range ("iterator is out of range"); Returns the content pointed to by the current pointer return currentnode->data; Template <typename Type>type &listiterator<type>::operator* () throw (Std::out_of_range) {return C Onst_cast<type &> (static_cast<const listiterator<type> &> (*this). operator* () );}
template <typename type>const doublelistnode<type> *listiterator<type>::operator-> () Constthrow (std::o Ut_of_range) {if (IsEmpty ()) Throw Std::out_of_range ("iterator is out of range"); Return directly to the pointer return currentnode;} Template <typename type>doublelistnode<type> *listiterator<type>::operator-> () throw (std::out _of_range) {return const_cast<doublelistnode<type> *> (Static_cast<const listiterator <Type> > (*this) .operator-> ());}
template <typename type>listiterator<type> &listiterator<type>::operator++ () throw (std::out_of_range {if (IsEmpty ()) Throw Std::out_of_range ("iterator is out of range"); Pointer move forward CurrentNode = currentnode->next; return *this;} Template <typename type>listiterator<type> listiterator<type>::operator++ (int) throw (std::out_of _range) {listiterator tmp (*this); + + (*this); Call the previous + + version of return tmp;}
Template <typename type>listiterator<type> &listiterator<type>::operator--() { //pointer move forward CurrentNode = currentnode->prev; return *this;} Template <typename type>listiterator<type> listiterator<type>::operator--(int) { listiterator<type> tmp (*this); --(*this); return TMP;}
Test Code :
int main () {cout << "--------1--------" << Endl; Doublelist<int> myList; for (int i = 0; i < 3; ++i) Mylist.push_back (i+1); for (int i = 0; i < 5; ++i) Mylist.push_front (10+i); for (int i = 0; i < 3; ++i) Mylist.push_back (i+1); Listiterator<int> iter (myList), Iter2 (myList); while (!iter.isempty ()) {cout << *iter << "; + + iter; + + Iter2; } cout << Endl; --Iter2; while (!iter2.isempty ()) {cout << *iter2 << "; Iter2--; } cout << Endl; cout << "--------2--------" << Endl; cout << myList << Endl; cout << "Test insert ..." << Endl; Mylist.insert (1, 14); Mylist.insert (2, 13); Mylist.insert (2, 13); Mylist.insert (88, 88); cout << myList << Endl; Mylist.pop_back (); Mylist.pop_front (); cout << myList << Endl; for (int i = 0; I < 5; ++i) {if (Mylist.search (i)) cout << i << ": Have found!" << Endl; else cout << i << ": Not in the list!" << Endl; } cout << "Test remove ..." << Endl; cout << myList << Endl; int value; while (Cin >> value) {try {mylist.remove (value); } catch (const std::exception &e) {cerr << e.what () << Endl; } cout << myList << Endl; if (Mylist.isempty ()) {cout << "empty" << Endl; } else {cout << "not empty" << Endl; }} return 0;}
Data Structure Foundation (12)--design and implementation of two-way cyclic chain list