【C++】容器介面卡實現佇列Queue的各種功能(入隊、出隊、判空、大小、訪問所有元素等)
阿新 • • 發佈:2019-02-15
介面卡:
將一個通用的容器轉換為另外的容器,所謂的容器,指的是存放資料的器具,像我們知道的順序表和連結串列都是容器Container。舉個例子解釋一下吧,我們的電壓都是220v,而像充電線就起到轉換到合適的電壓的作用。而這裡,我們的主角就是將通用的連結串列結構轉換為來實現佇列Queue這一資料結構,(意思就是,連結串列還可以去實現其他的資料結構)。
線上性表中,分為連結串列和順序表,我們知道其中的差別:
連結串列:節點靈活,使得插入刪除元素方便靈活,但是對於單鏈表若有節點指標_head、_tail,查詢元素較為麻煩,需要遍歷。
順序表:開闢一塊連續的記憶體空間,查詢元素方便,通過指標或者下標來訪問。插入或者刪除元素呢,又較為複雜,插入時需要將後面的元素挨著挨著全部後移,刪除元素後又需要將後面的元素全部前移。
針對佇列Queue模型,我們知道它是尾插頭刪、先進先出的特點。因此我針對以上原因選用連結串列結構來實現佇列Queue。可以參照下圖:
程式碼如下:
#include<iostream> using namespace std; #include<assert.h> template<class T> struct ListNode { ListNode(const T& x) :_next(NULL) , _prev(NULL) , _data(x) {} ListNode<T>* _next; ListNode<T>* _prev; T _data; }; template<class T> class List { public: List() :_head(NULL) , _tail(NULL) {} List(const List<T>& l) { ListNode<T>* cur = l._head; while (cur) { this->PushBack(cur->_data); cur = cur->_next; } } List<T>& operator=(const List<T>& l) { //先刪除節點,再插入節點 if (&s != this) { ListNode<T>* pcur = _head; while (pcur) { ListNode<T>* del = pcur; pcur = pcur->_next; delete del; del = NULL; } ListNode<T>* cur = _head; while (cur) { this->PushBack(cur->_data); cur = cur->_next; } } return *this; } ~List()//一個節點一個節點的刪除 { ListNode<T>* cur = _head; while (cur) { ListNode<T>* del = cur; cur = cur->_next; delete del; del = NULL; } } void PushBack(const T& x); void PopBack(); void PopFront(); void PrintList(); void Reverse(); size_t Length(); public: ListNode<T>* _head; ListNode<T>* _tail; }; //尾插 template<class T> void List<T>::PushBack(const T& x) { //分析:分為兩種情況:無節點、有節點 if (_head == NULL) { _head = _tail = new ListNode<T>(x); } else { ListNode<T>* cur = new ListNode<T>(x); _tail->_next = cur; cur->_prev = _tail; _tail = cur; _tail->_next = NULL; } } //尾刪 template<class T> void List<T>::PopBack() { //分析:分為三種情況:無節點、一個節點、多個節點 if (_head == _tail) { if (_head == NULL) { return; } else { delete _head; _head = _tail = NULL; } } else { ListNode<T>* prev = _tail->_prev; delete _tail; _tail = NULL; _tail = prev; _tail->_next = NULL; } } //頭刪 template<class T> void List<T>::PopFront() { if (_head == _tail) { if (_head == NULL) { return; } delete _head; _head = _tail = NULL; } else { ListNode<T>* cur = _head; ListNode<T>* del = _head; _head = cur->_next; delete del; del = NULL; _head->_prev = NULL; } } //逆置 template<class T> void List<T>::Reverse() { //分析:從兩頭開始走,交換資料(分奇數個數據和偶數個數據) ListNode<T>* begin = _head; ListNode<T>* end = _tail; while (!((begin == end) || end->_next == begin)) { swap(begin->_data, end->_data); begin = begin->_next; end = end->_prev; } } //長度 template<class T> size_t List<T>::Length() { ListNode<T>* cur = _head; int count = 0; while (cur) { ++count; cur = cur->_next; } return count; } //列印 template<class T> void List<T>::PrintList() { ListNode<T>* cur = _head; while (cur) { cout << cur->_data << "->"; cur = cur->_next; } cout << "NULL" << endl; } template<class T, template<class> class Container = List> //預設形式 class Queue { public: //入隊 void Push(const T& x) { _con.PushBack(x); } //出隊 void Pop() { _con.PopFront(); } //大小 size_t Size() { return _con.Length(); } //判空 bool Empty() { return Size() == 0; } //隊頭 T& Front() { size_t size = Size(); assert(size > 0); return _con._head->_data; } //隊尾 T& Back() { size_t size = Size(); assert(size > 0); return _con._tail->_data; } protected: Container<T> _con; }; //佇列的測試函式 void TestQueue() { Queue<int, List> q1; //Queue<int> q1; q1.Push(1); q1.Push(2); q1.Push(3); q1.Push(4); q1.Push(5); //訪問佇列所有元素(佇列是插尾刪頭) while (!q1.Empty()) { cout<< q1.Front() << " "; q1.Pop(); } } int main() { TestQueue(); system("pause"); return 0; }