普通隊列效率低下,主要體現在出隊操作。
這里只討論環形隊列。
隊列的核心思想是FIFO(First In First Out),即先入先出。
入隊(新增元素)必須從隊尾加入,出隊(刪除元素)必須從隊首出去。
源代碼:https://github.com/cjy513203427/C_Program_Base/tree/master/51.%E9%98%9F%E5%88%97
需要實現的方法
#pragma once #include<iostream> using namespace std; #ifndef MYQUEUE_H #define MYQUEUE_H //環形隊列的實現 class MyQueue { public: MyQueue(int queueCapacity);//創建隊列 virtual ~MyQueue();//銷毀隊列 void ClearQueue();//清空隊列 bool QueueEmpty() const;//判空隊列 bool QueueFull() const;//判滿隊列 int QueueLength() const;//隊列長度 bool EnQueue(int element);//新元素入隊 bool DeQueue(int &element);//首元素出隊 void QueueTraverse();//遍歷隊列 private: int *m_pQueue;//隊列數組指針 int m_iQueueLen;//隊列元素個數 int m_iQueueCapacity;//隊列數組容量 int m_iHead; int m_iTail; }; #endif // !MYQUEUE_H
1.隊列構造函數
隊列容量作為參數傳入;
聲明指向數組的指針,賦予容量;
清空隊列的方法如“3.清空隊列的實現”
MyQueue::MyQueue(int queueCapacity) { m_iQueueCapacity = queueCapacity; m_pQueue = new int[m_iQueueCapacity]; ClearQueue(); }
2.隊列析構函數
刪除指針,並置空。因為是指向數組的指針,使用delete[]
MyQueue::~MyQueue() { delete[] m_pQueue; m_pQueue = NULL; }
3.清空隊列
將隊首置為0,隊尾置0,隊列長度置0
void MyQueue::ClearQueue() { m_iHead = 0; m_iTail = 0; m_iQueueLen = 0; }
4.判空與判滿
判空:長度等於0返回正確的結果,否則錯誤
判滿:長度等於容量返回正確的結果,否則錯誤
bool MyQueue::QueueEmpty() const { return m_iQueueLen == 0 ? true : false; } bool MyQueue::QueueFull() const { return m_iQueueLen == m_iQueueCapacity ? true : false; }
5.隊列長度
bool MyQueue::QueueEmpty() const { return m_iQueueLen == 0 ? true : false; }
6.入隊操作
如果隊列已滿,不允許入隊
如果隊列未滿,傳入需要加入的參數
將數組[隊尾]置為傳入的元素
隊尾++
隊列長度++
隊尾對容量進行取余,防止隊尾溢出,一旦隊尾大於等於4,就會回歸到0-4之間的數,從而達到環形隊列的目的
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; } }
7.出隊操作
如果隊列為空,不允許出隊
如果隊列不為空,允許出隊
把即將刪除的數組[隊首]賦值給引用,隊首++,出隊的元素下一個成為新的隊首元素
隊首對容量進行取余操作,防止溢出隊列容量
隊列長度--
PS:這里的引用是為了獲取到實參的值,這個參數並不會影響到隊列數據,實際上是為了返回這個實參,相當於int MyQueue::Dequeue(){return element},但是這里需要返回類型是bool,又想得到實參的值,只能傳入引用了
這個特性在Java里面不存在
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; } }
8.遍歷操作
因為要循環m_iQueueLen次,所以隊列長度要加上m_iHead(隊首),i對容量取余防止隊列容量溢出
void MyQueue::QueueTraverse() { for (int i = m_iHead; i < m_iQueueLen + m_iHead; i++) { cout << m_pQueue[i%m_iQueueCapacity] << endl; } }