參考鏈接:數據結構探險—隊列篇
數據結構太重要了,不學好是沒法進行軟件開發的。
C++寫數據結構基本套路:一個.h文件寫該數據結構類的接口;一個.cpp文件寫接口的具體實現;一個main.cpp用於測試。
隊列
隊列的模型
想象一下現實生活中的隊列,排隊先入先出,不允許插隊,隊頭先出,隊尾進入。(應用:營業廳自動排號機)
隊列的編程實現方式
環形隊列,數組實現,靜態的,事先確定隊列容量,人為取余,循環利用數組資源。
普通隊列,
鏈表實現,動態的,有點浪費,因為插入刪除只在隊列頭尾進行
。
隊列的基本元素
要操縱隊列,必須要有一個數組(指針),隊列長度,隊列容量;然后用隊列頭和隊列尾操縱隊列。
環形隊列中隊列頭和隊列尾到底意味着什么?對尾指向最后一個元素的下一個位置。
隊列的基本操作
創建隊列,銷毀隊列,清空隊列,隊列判空,隊列判滿,隊列長度;元素入隊,元素出對,遍歷隊列
基本操作的實現
創建隊列:構造函數實現,函數參數為隊列容量;此步需要完成的任務:形成數組實體,即分配內存,將一些隊列基本元素初始化。
銷毀隊列:析構函數實現,釋放內存,指針置空。
清空隊列:指針不動,基本元素初始化
隊列判空:通過長度判斷
隊列判滿:通過長度和容量判斷
隊列長度:直接返回
元素入隊:判斷能否插入,能則插入,更新隊列基本信息(技巧)
元素出對:判斷是否有東西可以刪除,更新隊列基本信息
遍歷隊列:循環,從頭到尾,遍歷(輸出)
大部分的操作都是針對隊列基本元素的,會利用和改變它。(所以用C++其實是簡化了,只需考慮類內數據元素)
寫一個大型的數據結構很難,很容易就會出現某些細小的錯誤,如果無法控制這些細小的錯誤,那等程序大起來之后,就很難很難找錯和調試了。
C++實現步驟
- 首先,把上面的流程走一遍,做到心中有數。
- 設計隊列的接口(建議寫在一個單獨文檔里,以便隨時查閱),先不談具體實現;(照着抄很容易,關鍵要會默寫)
- 實現,核心功能,創建,插入,刪除,遍歷顯示,調試成功
- 補充其他核心功能
代碼要寫好,還真是太難了,首先要正確的命名,其次大小寫還不能搞錯,在使用的時候還要一一對應。
函數的返回值、函數名、參數等等,都不允許有錯誤。(很難一次性寫好,在實現時慢慢修正)
初次親手敲代碼的體會:隊列的代碼量確實很少,接口20多行;實現80多行,測試20多行,根本就不算多;但是寫起來還是感覺很難,之前敲書本上的單個例題,感覺還沒什么難度;隊列元素太多,基本的5個元素,操作太多,9個基本操作,操作之間部分依賴;我對C++的語法也不算太熟悉,有些卡頓;東西太多,太雜,名稱太長,導致我眼花繚亂。
課程筆記
這是之前C++的進階課,數據結構:一群數據以及數據之間的關系(集合+關系),數據結構是前人經驗的總結,所以你學習借鑒就好了,不要鑽牛角尖。
隊列是先入先出的數學模型,隊列中很少用到位序,因為只能對首尾進行操作,載入元素默認實在隊尾,刪除元素默認是在隊頭。
隊列分為普通隊列和環形隊列
普通隊列:分兩種情況,一是隊頭離開,后面全部前移;二是隊頭離開,不移,往后繼續排,這兩種結果都不好
環形隊列:充分利用資源,也不犧牲效率;隊頭隊尾重疊只有兩種情況,要么為空,要么為滿。
隊列的C和C++實現方式是大為不同的
在C++中,隊列被寫成了類,每一個具體隊列都是該類的實例;而C語言中,只是簡單定義了個結構體,C語言函數的參數中一定要含有隊列的地址,而C++因為寫在了類中,則不用傳參數。
標准C++代碼
#pragma once //MyQueue.h //環形隊列C++實現 class MyQueue { public: MyQueue(int queueCapacity); //InitQueue(&Q)創建隊列 virtual ~MyQueue(); //DestroyQueue(&Q)銷毀隊列 void ClearQueue(); //ClearQueue(&Q)清空隊列 bool QueueEmpty() const; //QueueEmpty(&Q)判空隊列 int QueueLength() const; //QueueLength(Q)隊列長度 bool QueueFull() const; bool EnQueue(int element); //EnQueue(&Q, element)新元素入隊 bool DeQueue(int &element); //DeQueue(&Q, &element)首元素出隊 void QueueTraverse(); //QueueTraverse(Q, visit())遍歷隊列 private: int *m_pQueue; //隊列數組數組 int m_iQueueLen; //隊列元素個數 int m_iQueueCapacity; //隊列數組容量 int m_iHead; int m_iTail; };
//MyQueue.cpp #include"MyQueue.h" #include<iostream> using namespace std; MyQueue::MyQueue(int queueCapacity) { m_iQueueCapacity = queueCapacity; m_iHead = 0; m_iTail = 0; m_iQueueLen = 0; m_pQueue = new int[m_iQueueCapacity]; } MyQueue::~MyQueue() { delete[]m_pQueue; m_pQueue = nullptr; } void MyQueue::ClearQueue() { m_iHead = 0; m_iTail = 0; m_iQueueLen = 0; } bool MyQueue::QueueEmpty() const { if (m_iQueueLen == 0) return true; else return false; } bool MyQueue::QueueFull() const { if (m_iQueueLen == m_iQueueCapacity) return true; else return false; } int MyQueue::QueueLength() const { return m_iQueueLen; } bool MyQueue::EnQueue(int element) { if (QueueFull()) return false; else { m_pQueue[m_iTail] = element; m_iTail++; m_iTail = m_iTail % m_iQueueCapacity; m_iQueueLen++; return true; } } bool MyQueue::DeQueue(int &element) { if (QueueEmpty()) return false; else { element = m_pQueue[m_iHead]; m_iHead++; m_iHead = m_iHead % m_iQueueCapacity; m_iQueueLen--; return true; } } void MyQueue::QueueTraverse() { for (int i = m_iHead; i < m_iQueueLen + m_iHead; i++) { cout << m_pQueue[i%m_iQueueCapacity] << endl; } }
//demo.cpp #include<iostream> #include"MyQueue.h" using namespace std; int main() { MyQueue *p = new MyQueue(4); p->EnQueue(1); p->EnQueue(0); p->EnQueue(11); p->QueueTraverse(); p->ClearQueue(); cout << "after clear: " << endl; p->QueueTraverse(); if (p->QueueEmpty()) cout << "Empty queue" << endl; else cout << "Not Empty" << endl; p->EnQueue(5); p->EnQueue(15); p->EnQueue(25); cout << p->QueueLength() << endl; int tmp; p->DeQueue(tmp); cout << "tmp is " << tmp << endl; cout << p->QueueLength() << endl; return 0; }
實際應用
節點的數據可以是任意類型的數據,ElemType為Customer
//Customer.h #pragma once #include <string> using namespace std; class Customer { public: Customer(string name = "", int age = 0); void printInfo() const; private: string m_strName; int m_iAge; };
//Customer.cpp #include<iostream> #include"Customer.h" using namespace std; Customer::Customer(string name, int age) { m_strName = name; m_iAge = age; } void Customer::printInfo() const { cout << "Name: " << m_strName << endl; cout << "Age: " << m_iAge << endl; cout << "=================" << endl; }
//demo.cpp #include<iostream> #include"MyQueue.h" using namespace std; int main() { MyQueue *p = new MyQueue(4); Customer c1("zhangsan", 20); Customer c2("lisi", 30); Customer c3("wangwu", 24); p->EnQueue(c1); p->EnQueue(c2); p->EnQueue(c3); p->QueueTraverse(); cout << endl; Customer c4; p->DeQueue(c4); cout << "this is c4: " << endl; c4.printInfo(); cout << "this is QueueTraverse: " << endl; p->QueueTraverse(); return 0; }
使用C++模板寫一個隊列