Data Structure BASICS (12) and data structure basics 12

Source: Internet
Author: User

Data Structure BASICS (12) and data structure basics 12

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 <typename Type> class DoubleListNode {// friend element declaration friend class DoubleList <Type>; friend class ListIterator <Type>; template <typename T> friend ostream & operator <(ostream & OS, const DoubleList <T> & list); private: DoubleListNode (const Type & dataValue): data (dataValue ), prev (NULL), next (NULL) {} Type data; DoubleListNode * prev; // forward pointer field DoubleListNode * next; // post pointer field };

Bidirectional cyclic linked list structure:

Template <typename Type> class DoubleList {friend class ListIterator <Type>; template <typename T> friend ostream & operator <(ostream & OS, const DoubleList <T> & 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 <Type> * previous, doubleListNode <Type> * x); void removePrivate (DoubleListNode <Type> * x); private: DoubleListNode <Type> * first ;};

Structure and analysis of linked lists:

// Construct the linked list template <typename Type> DoubleList <Type >:: DoubleList () {first = new DoubleListNode <Type> (0); first-> next = first; first-> prev = first ;}
// Destructor linked list template <typename Type> DoubleList <Type> ::~ DoubleList () {DoubleListNode <Type> * deleteNode = NULL; // Save the end element of the linked list DoubleListNode <Type> * 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:

// Same as the private member // Insert the 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 the 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 provided to the customer:

// Insert the template to the end of the table <typename Type> void DoubleList <Type >:: push_back (const Type & data) {DoubleListNode <Type> * newNode = new DoubleListNode <Type> (data); // locate the first node DoubleListNode <Type> * previous = first-> prev; // insert insertPrivate (previous, newNode);} // insert it to the header template <typename Type> void DoubleList <Type >:: push_front (const Type & data) {DoubleListNode <Type> * newNode = new DoubleListNode <Type> (data); // insert InsertPrivate (first, newNode);} // insert to any position (specified according to position) template <typename Type> void DoubleList <Type >:insert (int position, const Type & data) {if (position = 1) return push_front (data); int count = 1; // previous indicates a position before the position to be inserted DoubleListNode <Type> * 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 <Type> * newNode = new DoubleListNode <Type> (data); insertPrivate (previous, newNode );}

Deletion provided to the customer:

// Delete the last element template <typename Type> void DoubleList <Type >:: pop_back () {removePrivate (first-> prev );} // Delete the Header element template <typename Type> void DoubleList <Type >:: pop_front () {removePrivate (first-> next );} // Delete the 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 );}}

Check whether 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;}

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

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 a two-way cyclic linked list iterator:
// Except operator -- added, almost no template <typename Type> class ListIterator {public: ListIterator (const DoubleList <Type> & _ 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 <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 returned value is, instead of 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 <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"); // return the content pointed to by the current pointer: return currentNode-> data;} template <typename Type> Type & ListIterator <Type> :: operator * () throw (std: out_of_range) {return const_cast <Type &> (static_cast <const ListIterator <Type> &> (* this ). operator *());}
Template <typename Type> const DoubleListNode <Type> * ListIterator <Type>: 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 <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"); // the pointer moves forward currentNode = currentNode-> next; return * this ;} template <typename Type> ListIterator <Type>: operator ++ (int) throw (std: out_of_range) {ListIterator tmp (* this ); ++ (* this); // call the forward ++ version return tmp ;}
Template <typename Type> ListIterator <Type> & ListIterator <Type>: operator -- () {// forward the pointer currentNode = currentNode-> prev; return * this ;} template <typename 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;}

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.