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,說明正確。