程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Circular Doubly Linked List 雙向循環鏈表 C++ 例子

Circular Doubly Linked List 雙向循環鏈表 C++ 例子

編輯:C++入門知識

What a circular doubly linked list looks like?

 

\

 


Look at Figure1, It is a circular doubly linked list have 8 nodes. If you compare it and the array in Figure2, you will find that each node in doubly linked list points to the next node and pre node in the list. Because of the way that linked lists are structured, you can easily add or remove nodes at the beginning or the end of a list, or even in the middle of the list. Below is a list class with simple property. We will add "Insert", "Delete" and other function later.

 

[cpp]
template <class T> class List; 
 
template <class T> 
class Node{ 
    friend List<T>; 
private: 
    T data; 
    Node<T>* pre,* next; 
}; 
 
template <class T> 
class List{ 
private: 
    Node<T>* first; 

template <class T> class List;

template <class T>
class Node{
 friend List<T>;
private:
 T data;
 Node<T>* pre,* next;
};

template <class T>
class List{
private:
 Node<T>* first;
}

 

How to insert a node
There are four cases when you insert a node into the linked list. (1) insert the node at the beginning of the list,  (2) insert the node at the middle of the list, (3) insert the node at the end of the list, (4) out of range

(1). The new node will become the new first node in the list.


(3). The new node will become the new tail node in the list.

(4). Throw a exception


We will talk detail about the second case using three figures below.

 

 

 

 

 

 

 

[cpp]
template<class T> 
void List<T>::Insert(const int& position, const T& v){ 
    if(position < 0 || position > Size()){ 
        throw OutOfBounds(); 
    } 
    Node<T>* newNode = new Node<T>; 
    newNode->data = v; 
 
    if(position == 0){// at the beginning of the list  
        if(!first){ //the list is empty  
            first = newNode; 
            first->next = first->pre = first; 
        }else{ //the new node became the first node  
            newNode->next = first; 
            first->pre = newNode; 
 
            newNode->pre = first->pre; 
            first->pre->pre->next = newNode; 
            first = newNode; 
        } 
    }else{ //at the middle or end of the list  
        Node<T>* nodeBeforePostion = first; 
        //find the node before insert position  
        for(int i = 1; i < position && nodeBeforePostion; ++i){ 
            nodeBeforePostion = nodeBeforePostion->next; 
        } 
        newNode->next = nodeBeforePostion->next; 
        newNode->next->pre = newNode; 
        newNode->pre = nodeBeforePostion; 
        nodeBeforePostion->next = newNode;        
    } 
    ++size; 

template<class T>
void List<T>::Insert(const int& position, const T& v){
 if(position < 0 || position > Size()){
  throw OutOfBounds();
 }
 Node<T>* newNode = new Node<T>;
 newNode->data = v;

 if(position == 0){// at the beginning of the list
  if(!first){ //the list is empty
   first = newNode;
   first->next = first->pre = first;
  }else{ //the new node became the first node
   newNode->next = first;
   first->pre = newNode;

   newNode->pre = first->pre;
   first->pre->pre->next = newNode;
   first = newNode;
  }
 }else{ //at the middle or end of the list
  Node<T>* nodeBeforePostion = first;
  //find the node before insert position
  for(int i = 1; i < position && nodeBeforePostion; ++i){
   nodeBeforePostion = nodeBeforePostion->next;
  }
  newNode->next = nodeBeforePostion->next;
  newNode->next->pre = newNode;
  newNode->pre = nodeBeforePostion;
  nodeBeforePostion->next = newNode;  
 }
 ++size;
}

 

 

 

 

How to delete a node

 

There three cases when you delete a node in the list. (1) Delete the first node, (2) Delete a node at the middle position of the list, (3) out of range

(1). The first node's next node become the new first node.

(3). Throw a exception.


Figure 6,7 and 8 show a graphical representation of how the case 2 acts.

 

 

 

 

 

 

 

 

[cpp]
template<class T> 
void List<T>::Delete(const int& position, T& out){ 
    if(position < 0 || position > Size() || !first){ 
        throw OutOfBounds(); 
    } 
 
    if(position == 0){// at the beginning of the list  
        out = first->data; 
        Node<int>* tmp = first->next; 
        if(tmp == first){ //only one node,just delete it  
            delete first; 
            first = 0; 
        }else{ // set first node's next node to be the new first node,delete the old first node  
            first->pre->next = first->next; 
            first->next->pre = first->pre; 
            delete first; 
            first = tmp; 
        } 
    }else{//at the middle or end of the list  
        Node<T>* nodeDelete = first; 
        //find the node which need to delete  
        for(int i = 0; i< position && nodeDelete->next != first; ++i){ 
            nodeDelete = nodeDelete->next; 
        } 
        nodeDelete->pre->next = nodeDelete->next; 
        nodeDelete->next->pre = nodeDelete->pre; 
        out = nodeDelete->data; 
        delete nodeDelete; 
 
    } 
    --size; 

template<class T>
void List<T>::Delete(const int& position, T& out){
 if(position < 0 || position > Size() || !first){
  throw OutOfBounds();
 }

 if(position == 0){// at the beginning of the list
  out = first->data;
  Node<int>* tmp = first->next;
  if(tmp == first){ //only one node,just delete it
   delete first;
   first = 0;
  }else{ // set first node's next node to be the new first node,delete the old first node
   first->pre->next = first->next;
   first->next->pre = first->pre;
   delete first;
   first = tmp;
  }
 }else{//at the middle or end of the list
  Node<T>* nodeDelete = first;
  //find the node which need to delete
  for(int i = 0; i< position && nodeDelete->next != first; ++i){
   nodeDelete = nodeDelete->next;
  }
  nodeDelete->pre->next = nodeDelete->next;
  nodeDelete->next->pre = nodeDelete->pre;
  out = nodeDelete->data;
  delete nodeDelete;

 }
 --size;
}

 

 

Circular Double Linked List Customized Class

[cpp]
#ifndef _List_  
#define _List_  
 
#include <iostream>  
 
using namespace std; 
 
//exception  
class OutOfBounds{ 
public: 
    OutOfBounds(){} 
}; 
 
template <class T> class List; 
 
template <class T> 
class Node{ 
    friend List<T>; 
private: 
    T data; 
    Node<T>* pre,* next; 
}; 
 
 
template <class T> 
class List{ 
    //overwrite operator <<  
    template<class T> friend ostream& operator<<(ostream& ,List<T>&); 
private: 
    Node<T>* first; 
    int size; 
 
    bool firstTime;//used for print list element.  
    Node<T>* current; 
     
public: 
 
    List(){first = 0; size = 0;} 
    ~List(); 
    void Delete(const int& position, T& out); 
    void Delete(const int& position); 
    void Insert(const int& position, const T& x); 
    void Push_Back(const T& v); 
    int Size()const; 
    T Front()const; 
    T Back()const; 
    void Begin(); 
    void MoveNext(); 
    bool Valid(); 
    T GetItemData() const; 
    void Clear(); 
 
}; 
 
template<class T> 
ostream& operator<< (ostream& out,List<T>& list){ 
    out << "The list's size: " << list.Size() << endl; 
    out << "The list's front: "; 
    try{ 
        out << list.Front() << endl; 
    }catch(OutOfBounds ){ 
        out << "No element in the list" << endl; 
    } 
    out << "The list's back: "; 
    try{ 
        out << list.Back() << endl; 
    }catch(OutOfBounds ){ 
        out << "No element in the list" << endl; 
    } 
    out << "Elements in the list:" << endl; 
    for(list.Begin(); list.Valid(); list.MoveNext()){ 
        out << list.GetItemData() << ' '; 
    } 
    out << endl; 
    return out; 

 
template<class T> 
List<T>::~List(){ 
    Clear(); 

 
template<class T> 
void List<T>::Delete(const int& position){ 
    T value; 
    Delete(position, value); 

 
template<class T> 
void List<T>::Delete(const int& position, T& out){ 
    if(position < 0 || position > Size() || !first){ 
        throw OutOfBounds(); 
    } 
 
    if(position == 0){// at the beginning of the list  
        out = first->data; 
        Node<int>* tmp = first->next; 
        if(tmp == first){ //only one node,just delete it  
            delete first; 
            first = 0; 
        }else{ // set first node's next node to be the new first node,delete the old first node  
            first->pre->next = first->next; 
            first->next->pre = first->pre; 
            delete first; 
            first = tmp; 
        } 
    }else{//at the middle or end of the list  
        Node<T>* nodeDelete = first; 
        //find the node which need to delete  
        for(int i = 0; i< position && nodeDelete->next != first; ++i){ 
            nodeDelete = nodeDelete->next; 
        } 
        nodeDelete->pre->next = nodeDelete->next; 
        nodeDelete->next->pre = nodeDelete->pre; 
        out = nodeDelete->data; 
        delete nodeDelete; 
 
    } 
    --size; 

 
template<class T> 
void List<T>::Insert(const int& position, const T& v){ 
    if(position < 0 || position > Size()){ 
        throw OutOfBounds(); 
    } 
    Node<T>* newNode = new Node<T>; 
    newNode->data = v; 
 
    if(position == 0){// at the beginning of the list  
        if(!first){ //the list is empty  
            first = newNode; 
            first->next = first->pre = first; 
        }else{ //the new node became the first node  
            newNode->next = first; 
            first->pre = newNode; 
 
            newNode->pre = first->pre; 
            first->pre->pre->next = newNode; 
            first = newNode; 
        } 
    }else{ //at the middle or end of the list  
        Node<T>* nodeBeforePostion = first; 
        //find the node before insert position  
        for(int i = 1; i < position && nodeBeforePostion; ++i){ 
            nodeBeforePostion = nodeBeforePostion->next; 
        } 
        newNode->next = nodeBeforePostion->next; 
        newNode->next->pre = newNode; 
        newNode->pre = nodeBeforePostion; 
        nodeBeforePostion->next = newNode;        
    } 
    ++size; 

 
template<class T> 
void List<T>::Push_Back(const T& v){ 
    Node<T>* newNode = new Node<T>; 
    newNode->data = v; 
    if(!first){ // the list is empty  
        first = newNode; 
        first->next = first->pre = first; 
    }else{ 
        Node<T>* lastNode = first->pre; 
        first->pre = newNode; 
        newNode->next = first; 
        lastNode->next = newNode; 
        newNode->pre = lastNode; 
    } 
    ++size; 

 
template<class T> 
int List<T>::Size() const{ 
    return size; 

 
template<class T> 
T List<T>::Front() const{ 
    if(!first){ 
        throw OutOfBounds(); 
    }else{ 
        return first->data; 
    } 

 
template<class T> 
T List<T>::Back() const{ 
    if(!first){ 
        throw OutOfBounds(); 
    }else{ 
        return first->pre->data; 
    } 

 
template<class T> 
void List<T>::Begin(){ 
    current = first; 
    firstTime = true; 

 
template<class T> 
void List<T>::MoveNext(){ 
    current = current->next; 

 
template<class T> 
bool List<T>::Valid(){ 
    if(!first || (current == first && !firstTime)){ 
        return false; 
    }else{ 
        firstTime = false; 
        return true; 
    } 
}  
 
template<class T> 
T List<T>::GetItemData()const{ 
    return current->data; 

 
template<class T> 
void List<T>::Clear(){ 
    while(Size() != 0){ 
        Delete(0); 
    } 
    size = 0; 

 
#endif 

#ifndef _List_
#define _List_

#include <iostream>

using namespace std;

//exception
class OutOfBounds{
public:
 OutOfBounds(){}
};

template <class T> class List;

template <class T>
class Node{
 friend List<T>;
private:
 T data;
 Node<T>* pre,* next;
};


template <class T>
class List{
 //overwrite operator <<
 template<class T> friend ostream& operator<<(ostream& ,List<T>&);
private:
 Node<T>* first;
    int size;

 bool firstTime;//used for print list element.
 Node<T>* current;
 
public:

 List(){first = 0; size = 0;}
 ~List();
 void Delete(const int& position, T& out);
 void Delete(const int& position);
 void Insert(const int& position, const T& x);
 void Push_Back(const T& v);
 int Size()const;
 T Front()const;
 T Back()const;
 void Begin();
 void MoveNext();
 bool Valid();
 T GetItemData() const;
 void Clear();

};

template<class T>
ostream& operator<< (ostream& out,List<T>& list){
 out << "The list's size: " << list.Size() << endl;
 out << "The list's front: ";
 try{
  out << list.Front() << endl;
 }catch(OutOfBounds ){
  out << "No element in the list" << endl;
 }
 out << "The list's back: ";
 try{
  out << list.Back() << endl;
 }catch(OutOfBounds ){
  out << "No element in the list" << endl;
 }
 out << "Elements in the list:" << endl;
 for(list.Begin(); list.Valid(); list.MoveNext()){
  out << list.GetItemData() << ' ';
 }
 out << endl;
 return out;
}

template<class T>
List<T>::~List(){
 Clear();
}

template<class T>
void List<T>::Delete(const int& position){
 T value;
 Delete(position, value);
}

template<class T>
void List<T>::Delete(const int& position, T& out){
 if(position < 0 || position > Size() || !first){
  throw OutOfBounds();
 }

 if(position == 0){// at the beginning of the list
  out = first->data;
  Node<int>* tmp = first->next;
  if(tmp == first){ //only one node,just delete it
   delete first;
   first = 0;
  }else{ // set first node's next node to be the new first node,delete the old first node
   first->pre->next = first->next;
   first->next->pre = first->pre;
   delete first;
   first = tmp;
  }
 }else{//at the middle or end of the list
  Node<T>* nodeDelete = first;
  //find the node which need to delete
  for(int i = 0; i< position && nodeDelete->next != first; ++i){
   nodeDelete = nodeDelete->next;
  }
  nodeDelete->pre->next = nodeDelete->next;
  nodeDelete->next->pre = nodeDelete->pre;
  out = nodeDelete->data;
  delete nodeDelete;

 }
 --size;
}

template<class T>
void List<T>::Insert(const int& position, const T& v){
 if(position < 0 || position > Size()){
  throw OutOfBounds();
 }
 Node<T>* newNode = new Node<T>;
 newNode->data = v;

 if(position == 0){// at the beginning of the list
  if(!first){ //the list is empty
   first = newNode;
   first->next = first->pre = first;
  }else{ //the new node became the first node
   newNode->next = first;
   first->pre = newNode;

   newNode->pre = first->pre;
   first->pre->pre->next = newNode;
   first = newNode;
  }
 }else{ //at the middle or end of the list
  Node<T>* nodeBeforePostion = first;
  //find the node before insert position
  for(int i = 1; i < position && nodeBeforePostion; ++i){
   nodeBeforePostion = nodeBeforePostion->next;
  }
  newNode->next = nodeBeforePostion->next;
  newNode->next->pre = newNode;
  newNode->pre = nodeBeforePostion;
  nodeBeforePostion->next = newNode;  
 }
 ++size;
}

template<class T>
void List<T>::Push_Back(const T& v){
 Node<T>* newNode = new Node<T>;
 newNode->data = v;
 if(!first){ // the list is empty
  first = newNode;
  first->next = first->pre = first;
 }else{
  Node<T>* lastNode = first->pre;
  first->pre = newNode;
  newNode->next = first;
  lastNode->next = newNode;
  newNode->pre = lastNode;
 }
 ++size;
}

template<class T>
int List<T>::Size() const{
 return size;
}

template<class T>
T List<T>::Front() const{
 if(!first){
  throw OutOfBounds();
 }else{
  return first->data;
 }
}

template<class T>
T List<T>::Back() const{
 if(!first){
  throw OutOfBounds();
 }else{
  return first->pre->data;
 }
}

template<class T>
void List<T>::Begin(){
 current = first;
 firstTime = true;
}

template<class T>
void List<T>::MoveNext(){
 current = current->next;
}

template<class T>
bool List<T>::Valid(){
 if(!first || (current == first && !firstTime)){
  return false;
 }else{
  firstTime = false;
  return true;
 }
}

template<class T>
T List<T>::GetItemData()const{
 return current->data;
}

template<class T>
void List<T>::Clear(){
 while(Size() != 0){
  Delete(0);
 }
 size = 0;
}

#endif

 

Test the class

 


[cpp]
// CustomizedList.cpp : Defines the entry point for the console application.  
//  
 
#include "stdafx.h"  
#include "List.h"  
#include <iostream>  
 
using namespace std; 
 
int _tmain(int argc, _TCHAR* argv[]) 

 
    List<int> list; 
    int deleteValue; 
    cout << "after initialize list" << endl; 
    cout << list; 
 
    cout << "try to delete with no element" << endl; 
    try{ 
        list.Delete(0); 
    }catch(OutOfBounds){ 
        cout << "delete error" << endl; 
    } 
 
    cout << "after call list.Insert(1,1)" << endl; 
    try{ 
        list.Insert(1,1); 
    }catch(OutOfBounds){ 
        cout << "insert error" << endl; 
    } 
    cout << list; 
 
    cout << "after call list.Insert(0,1)" << endl; 
    try{ 
        list.Insert(0,1); 
    }catch(OutOfBounds){ 
        cout << "insert error" << endl; 
    } 
    cout << list; 
 
    cout << "try to delete out range" << endl; 
    try{ 
        list.Delete(2); 
    }catch(OutOfBounds){ 
        cout << "delete error" << endl; 
    } 
    cout << list; 
 
    cout << "after call list.Push_Back(2) " << endl; 
    list.Push_Back(2); 
    cout << list; 
 
    cout << "delete position 0" << endl; 
    try{ 
        list.Delete(0, deleteValue); 
    }catch(OutOfBounds){ 
        cout << "delete error" << endl; 
    } 
    cout << "delete value:" << deleteValue << endl; 
    cout << list; 
 
    for(int i =0;i< 10; ++i){ 
        list.Push_Back(i); 
    } 
    cout << list; 
 
    cout << "after call list.Clear()" << endl; 
    list.Clear(); 
    cout << list; 
 
    int i; 
    cin >> i; 
    return 0; 

// CustomizedList.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "List.h"
#include <iostream>

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{

 List<int> list;
 int deleteValue;
 cout << "after initialize list" << endl;
 cout << list;

 cout << "try to delete with no element" << endl;
 try{
  list.Delete(0);
 }catch(OutOfBounds){
  cout << "delete error" << endl;
 }

 cout << "after call list.Insert(1,1)" << endl;
 try{
  list.Insert(1,1);
 }catch(OutOfBounds){
  cout << "insert error" << endl;
 }
 cout << list;

 cout << "after call list.Insert(0,1)" << endl;
 try{
  list.Insert(0,1);
 }catch(OutOfBounds){
  cout << "insert error" << endl;
 }
 cout << list;

 cout << "try to delete out range" << endl;
 try{
  list.Delete(2);
 }catch(OutOfBounds){
  cout << "delete error" << endl;
 }
 cout << list;

 cout << "after call list.Push_Back(2) " << endl;
 list.Push_Back(2);
 cout << list;

 cout << "delete position 0" << endl;
 try{
  list.Delete(0, deleteValue);
 }catch(OutOfBounds){
  cout << "delete error" << endl;
 }
 cout << "delete value:" << deleteValue << endl;
 cout << list;

 for(int i =0;i< 10; ++i){
  list.Push_Back(i);
 }
 cout << list;

 cout << "after call list.Clear()" << endl;
 list.Clear();
 cout << list;

 int i;
 cin >> i;
 return 0;
}

 \

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved