Data Structure BASICS (12)-Design and Implementation of two-way circular linked list

Source: Internet
Author: User

Data Structure BASICS (12)-Design and Implementation of two-way circular linked list

Features of two-way linked list operation:

(1) "query" is the same as a single-chain table;

(2) When "insert" and "delete", you must modify the pointer in both directions.

However, for a two-way cyclic linked list, inserting at the end of the table is very fast. It only takes O (1) time, because there is a pointer to the front, therefore, the two-way cyclic linked list can easily find the elements at the end of the table. Therefore, the two-way cyclic linked list is suitable for frequent insertion at the end of the table.



Empty linked list:


Bidirectional cyclic linked list node structure:

Class DoubleListNode {private: Type data; DoubleListNode * prev; // The forward pointer field DoubleListNode * next; // The backward pointer field };

Because you need to use it in the DoubleList class, you need to transform it as follows:

Template
 
  
Class DoubleListNode {// friend element declaration friend class DoubleList
  
   
; Friend class ListIterator
   
    
; Template
    
     
Friend ostream & operator <(ostream & OS, const DoubleList
     
      
& List); private: DoubleListNode (const Type & dataValue): data (dataValue), prev (NULL), next (NULL) {} Type data; DoubleListNode * prev; // forward pointer field DoubleListNode * next; // backward pointer field };
     
    
   
  
 

Bidirectional cyclic linked list structure:

Template
 
  
Class DoubleList {friend class ListIterator
  
   
; Template
   
    
Friend ostream & operator <(ostream & OS, const DoubleList
    
     
& List); public: 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 to the void insertPrivate (DoubleListNode
     
      
* Previous, DoubleListNode
      
        * X); void removePrivate (DoubleListNode
       
         * X); private: DoubleListNode
        
          * First ;};
        
       
      
     
    
   
  
 

Structure and analysis of linked lists:

// Create a linked list template
 
  
DoubleList
  
   
: DoubleList () {first = new DoubleListNode
   
    
(0); first-> next = first; first-> prev = first ;}
   
  
 
// Analyze the linked list template
 
  
DoubleList
  
   
::~ DoubleList () {DoubleListNode
   
    
* DeleteNode = NULL; // Save the end element of the linked list DoubleListNode
    
     
* Tmp = first; // first point to the first real element first = first-> next; // all the way to the end of the linked list while (first! = Tmp) {deleteNode = first; first = first-> next; delete deleteNode;} // release the empty node (header) of the linked list to delete tmp ;}
    
   
  
 

Two main elements of linked list element insertion and deletion:

// The same as a private member // insert a node template
 
  
Void DoubleList
  
   
: InsertPrivate (DoubleListNode
   
    
* Previous, DoubleListNode
    
     
* X) {x-> prev = previous; x-> next = previous-> next; previous-> next-> prev = x; previous-> next = x ;}
    
   
  
 

// Delete the node template
 
  
Void DoubleList
  
   
: RemovePrivate (DoubleListNode
   
    
* 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 provided to the customer:

// Insert the template to the end of the table
 
  
Void DoubleList
  
   
: Push_back (const Type & data) {DoubleListNode
   
    
* NewNode = new DoubleListNode
    
     
(Data); // locate the first node DoubleListNode
     
      
* Previous = first-> prev; // insert insertPrivate (previous, newNode);} // insert it to the header template
      
        Void DoubleList
       
         : Push_front (const Type & data) {DoubleListNode
        
          * NewNode = new DoubleListNode
         
           (Data); // insertPrivate (first, newNode) after being inserted to first;} // insert to any position (specified by position) template
          
            Void DoubleList
           
             : Insert (int position, const Type & data) {if (position = 1) return push_front (data); int count = 1; // previous indicates a position before which DoubleListNode is to be inserted
            
              * Previous = first-> next; // if the position is too large, the previous will stop when it finds the first element. // at this time, the element should be inserted to the end of the linked list while (count <position-1 & previous! = First) {++ count; previous = previous-> next;} // if the end of the linked list is found or the linked list is empty at this time, therefore, insert it to the end of the table if (previous = first) return push_back (data); // if a suitable Insertion Location is found, DoubleListNode
             
               * NewNode = new DoubleListNode
              
                (Data); insertPrivate (previous, newNode );}
              
             
            
           
          
         
        
       
      
     
    
   
  
 

Deletion provided to the customer:

// Delete the end element template
 
  
Void DoubleList
  
   
: Pop_back () {removePrivate (first-> prev);} // Delete the Header element template
   
    
Void DoubleList
    
     
: Pop_front () {removePrivate (first-> next);} // Delete All template elements whose element value is removeData
     
      
Void DoubleList
      
        : Remove (const Type & removeData) {if (isEmpty () throw std: range_error ("link list is empty"); for (DoubleListNode
       
         * SearchNode = first-> next; searchNode! = First; searchNode = searchNode-> next) {if (searchNode-> data = removeData) removePrivate (searchNode );}}
       
      
     
    
   
  
 

Check whether it exists in the linked list:

template 
 
  bool DoubleList
  
   ::search(const Type &searchData) const{    DoubleListNode
   
     *searchNode = first->next;    while (searchNode != first)    {        if (searchNode->data == searchData)            return true;        searchNode = searchNode->next;    }    return false;}
   
  
 

Output all elements of the linked list (for testing ):

template 
 
  ostream &operator<<(ostream &os, const DoubleList
  
    &list){    for (DoubleListNode
   
     *currentNode = (list.first)->next;            currentNode != list.first;            currentNode = currentNode->next)        os << currentNode->data << ' ';    return os;}
   
  
 

Design and Implementation of a two-way cyclic linked list iterator:
// Except operator -- added, almost no template change is made.
 
  
Class ListIterator {public: ListIterator (const DoubleList
  
   
& _ List): list (_ list), currentNode (_ list. first)-> next) {}// reload * operator const Type & operator * () const throw (std: out_of_range); Type & operator * () throw (std :: out_of_range); // overload-> operator const DoubleListNode
   
    
* Operator-> () const throw (std: out_of_range); DoubleListNode
    
     
* Operator-> () throw (std: out_of_range); // overload + + operator ListIterator & operator ++ () throw (std: out_of_range); // note: here, the returned value is not reference ListIterator operator ++ (int) throw (std: out_of_range); // reload -- operator, // In fact, this version -- operator is not perfect, // The ListIterator & operator -- (); // Note: The value returned here is not the reference ListIterator operator -- (int); bool isEmpty () const {return (currentNode = list. first);} private: const DoubleList
     
      
& List; DoubleListNode
      
        * CurrentNode ;};
      
     
    
   
  
 
Template
 
  
Const Type & ListIterator
  
   
: Operator * () constthrow (std: out_of_range) {if (isEmpty () throw std: out_of_range ("iterator is out of range "); // return the content pointed to by the current pointer return currentNode-> data;} template
   
    
Type & ListIterator
    
     
: Operator * () throw (std: out_of_range) {return const_cast
     
      
(Static_cast
      
        &> (* This). operator *());}
      
     
    
   
  
 
Template
 
  
Const DoubleListNode
  
   
* ListIterator
   
    
: Operator-> () constthrow (std: out_of_range) {if (isEmpty () throw std: out_of_range ("iterator is out of range "); // directly return the pointer return currentNode;} template
    
     
DoubleListNode
     
      
* ListIterator
      
        : Operator-> () throw (std: out_of_range) {return const_cast
       
         *> (Static_cast
        
          > (* This). operator-> ());}
        
       
      
     
    
   
  
 
Template
 
  
ListIterator
  
   
& ListIterator
   
    
: Operator ++ () throw (std: out_of_range) {if (isEmpty () throw std: out_of_range ("iterator is out of range "); // forward the pointer to currentNode = currentNode-> next; return * this;} template
    
     
ListIterator
     
      
ListIterator
      
        : Operator ++ (int) throw (std: out_of_range) {ListIterator tmp (* this); ++ (* this ); // call the forward ++ version return tmp ;}
      
     
    
   
  
 
Template
 
  
ListIterator
  
   
& ListIterator
   
    
: Operator -- () {// Pointer Forward currentNode = currentNode-> prev; return * this;} template
    
     
ListIterator
     
      
ListIterator
      
        : Operator -- (int) {ListIterator
       
         Tmp (* this); -- (* this); return tmp ;}
       
      
     
    
   
  
 

Test code:

int main(){    cout << "-------- 1 --------" << endl;    DoubleList
 
   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
  
    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;}
  
 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.