用C++語言實現雙端隊列

1.目的

基於雙鏈表實現雙端隊列的典型操作(判空、頭插、頭刪、尾插、尾刪、普通構造、拷
貝構造、賦值運算符重 載、析構)

2.原理
雙端隊列頭插:
在這裏插入圖片描述
雙端隊列尾插:

在這裏插入圖片描述在這裏插入圖片描述
雙端隊列頭刪:
在這裏插入圖片描述
雙端隊列尾刪:
在這裏插入圖片描述
3.代碼
dlist.cpp

#include <iostream>

using namespace std;


template <typename T>
class Dlist {
public:
bool isEmpty() const;  //判空
void insertFront(T *o); //在表頭插入元素
void insertBack(T *o);  //在表尾插入元素
T *removeFront(); //刪除一個表頭元素
T *removeBack();  //刪除一個表尾元素
Dlist();  //構造函數
Dlist(const Dlist &l); //拷貝構造函數
Dlist& operator=(const Dlist &l); //"="運算符重載
~Dlist();  //析構函數
private:
struct Node {
    Node(){  //給指針賦初始值
        this->next = NULL;
        this->prev = NULL;
        this->o = NULL;
    }
Node *next; //指向下一個節點
Node *prev; //指向前一個節點
T *o;
};
Node *first;  //指向表頭
Node *last;   //指向表尾
void makeEmpty(); //建立一個空表
void removeAll(); //刪除表中所有元素
void copyAll(const Dlist &l); //將l表中的元素值拷貝到當前表
};

template <typename T>
bool Dlist<T>::isEmpty() const  //判空
{
    return first == NULL;
}

template <typename T>
void Dlist<T>::insertFront(T *o) //在表頭插入元素
{
    Node *new_node = new Node(); //定義一個新的節點

    new_node->o = o;  //給新節點賦初值,將要插入的值放入新節點
    if(first == NULL) //當原表爲空時,表明要插入的節點爲表頭
    {
        first = last = new_node;
    }
    else{ //當原表不爲空
        first->prev = new_node; //將原表頭的前指針指向新節點
        new_node->next = first; //將新節點的後指針指向原表頭
        first = new_node; //讓表頭指向新節點
    }
}

template <typename T>
void Dlist<T>::insertBack(T *o) //在表尾插入元素
{
    Node *new_node = new Node(); //定義一個新的節點

    new_node->o = o;  //給新節點賦初值,將要插入的值放入新節點
    if(first == NULL) //當原表爲空時,表明要插入的節點爲表頭
    {
        first = last = new_node;
    }
    else{ //當原表不爲空
        last->next = new_node; //將原表尾的後指針指向新節點
        new_node->prev = last; //將新節點的前指針指向原表尾
        last = new_node; //讓表尾指向新節點
    }
}

template <typename T>
T* Dlist<T>::removeFront() //刪除一個表頭元素
{
    Node *new_node = NULL; //定義一個新的節點
    T* p;

    if(NULL == first)
        return NULL; //如果表是空的則返回空
    new_node = first; //讓新指針指向表頭
    p = new_node->o; //保存表頭元素值
    first = first->next; //表頭向後移一位
    if(NULL != first)
    {
        first->prev = NULL; //新的表頭的前指針置空
    }
    else{
        first = NULL;  //如果表中無元素,將表頭置空
    }
    delete new_node; //刪除原表頭

    return p;
}

template <typename T>
T* Dlist<T>::removeBack() //刪除一個表尾元素
{
    Node *new_node = NULL; //定義一個新的節點
    T* p = NULL;
    if(NULL == first)
       {
           return NULL;//如果表是空的則返回空
       }
    new_node = last; //讓新指針指向表尾
    p = last->o; //保存表尾元素值
    last = last->prev; //表尾向前移一位
    if(last != NULL) //如果表尾前還有元素
    {
        last->next = NULL; //新的表尾的後指針置空
    }
    else{
        first = NULL; //如果表中無元素,將表頭置空
    }
    delete new_node; //刪除原表尾
    return p;
}

template <typename T>
Dlist<T>::Dlist() //構造函數
{
    makeEmpty();  //建立一個空表
}

template <typename T>
Dlist<T>::Dlist(const Dlist &l) //拷貝構造函數
{
    makeEmpty(); //建立一個空表
    copyAll(l);  //將l表元素複製到當前表
}

template <typename T>
Dlist<T>& Dlist<T>::operator=(const Dlist &l)  //"="運算符重載
{
    Dlist new_copy(l); //調用拷貝構造函數,將l表元素拷貝給new_copy
    removeAll(); //刪除原表中所有元素
    first = new_copy.first; //讓當前表的頭指針指向new_copy的頭指針
    last = new_copy.last; //讓當前表的尾指針指向new_copy的尾指針
    new_copy.first = NULL;
    new_copy.last = NULL;
    return *this; //返回當前表
}

template <typename T>
Dlist<T>::~Dlist()  //析構函數
{
    if( !isEmpty() ){  //當表不爲空時刪除所有元素
		removeAll();
	}
}

template <typename T>
void Dlist<T>::makeEmpty()  //建立一個空表
{
    first = NULL;  //初始化指向表頭的指針
    last = NULL;   //初始化指向表尾的指針
}

template <typename T>
void Dlist<T>::removeAll() //刪除表中所有元素
{
    Node *p = NULL;
	while(first != NULL){ //遍歷當前表,逐個刪除
		p = first;
		first = first->next;
		delete p;
	}
}

template <typename T>
void Dlist<T>::copyAll(const Dlist &l) //將l表中的元素值拷貝到當前表
{
    Node *old_node = NULL; //定義指針指向要拷貝的表
    old_node = l.first; //指向要拷貝的表的表頭
    while(old_node != NULL) //當要拷貝的表有元素時拷貝
    {
        insertBack(old_node->o);//將元素依次從後面插入當前表中
        old_node = old_node->next;
    }
}

測試類 distmain.cpp

#include <iostream>
#include "dlist.cpp"

using namespace std;

int main()
{
    Dlist<int> ilist;
    Dlist<int> one;
    int *ip = new int(3);
    int *j = new int(5);
    int *i = new int (7);
    int *p = new int();
    ilist.insertFront(ip);  //3
    ilist.insertFront(j);   //5 3
    ilist.insertBack(i);    //5 3 7
    one = ilist;  //測試“=”運算符重載
    p = one.removeFront(); //返回並刪除one的第一個數據
    cout << "one first number is:" << *p << endl; //結果應爲5
    Dlist<int> two(ilist); //測試拷貝構造函數
    p = two.removeFront(); //返回並刪除two的第一個數據
    cout << "two first number is:" << *p << endl; //結果應爲5
    ip = ilist.removeFront(); //返回並刪除ilist的第一個數據
    cout << "ilist first number is:" << *ip << endl; //結果應爲5
    j = ilist.removeBack(); //測試從末尾刪除元素,返回並刪除ilist的最後一個數據
    cout << "ilist last number is:" << *j << endl; //結果應爲7
    delete ip;
    delete j;
    delete i;
    delete p;
    return 0;
}

運行結果:
在這裏插入圖片描述
結果解釋:

 程序先依次從ilist表頭中插入3,5,然後從表尾插入7,則表中數據依次5,3,7.
 one表是用來測試“=”運算符重載函數的,讓one=ilist,取其頭元素的值。第一行值
 爲5,說明正確。
 two表是用來測試拷貝構造函數的,取其表頭的值,第二行值爲5,說明拷貝構造函數正確。
 第三行是測試從表頭返回並刪除元素,值爲5,說明正確。
 第四行是測試從表尾返回並刪除元素,值爲7,說明正確。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章