C++實現佇列(迴圈佇列)
一、佇列的操作:
、1、入隊(從尾入隊)
- 將值存入rear所代表的位置
- rear = (rear + 1)% 陣列的長度
2、 出隊(頭部出隊)
- front = (front + 1)% 陣列的長度
3、 佇列是否為空
- front 和 rear的值相等,則該佇列就一定為空
4、佇列是否已滿
在迴圈佇列中“隊滿”和“隊空”的條件有可能是相同的,都是front == rear 這種情況下,無法區別是“隊滿”還是“隊空”。針對這個問題有3種可能的處理方式:
(1)另設一個標誌以區別是“隊滿”還是”隊空“。
(2)設一個計數器,此時甚至還可以省去一個指標
(3)少一個元素空間,即約定隊頭指標在隊尾指標的下一個位置時就作為”隊滿“的標誌,即”隊滿“條件為:(pQueue->rear + 1)%MAX_SIZE == pQueue->front。
二、佇列的一些問題及解決辦法
從上圖可以看出,隨著入隊、出隊的進行,會使整個佇列整體向後移動,就會出現上圖種的現象:隊尾指標已經移到了最後,即隊尾出現溢位,無法再進行入隊操作,然而實際上,此時佇列中還是有空閒空間,這種現象稱為”假溢位“,解決假溢位的三種辦法:
方法一:每次刪除隊頭元素後,把整個佇列向前移動一個位置,這樣可保證隊頭元素在儲存空間的最前面。但每次刪除元素時,都要把表中所有元素向前移動,效率太低。
方法二:當隊尾指標出現溢位時,判斷隊頭指標位置,如果前部有空閒空間,則把當前佇列整體前移到最前方。這種方法移動元素的次數大為減少。
方法三:將佇列看成頭尾相接的迴圈結構,當隊尾指標到隊尾後,再從隊頭開始向後指,這樣就不需要移動佇列元素了,顯然,第三種方法最經濟、應用最多,這種順序佇列被稱為“迴圈佇列
採用了這種頭尾相接的迴圈佇列後,入隊的隊尾指標加1操作及出隊的隊頭指標加1操作必須做相應的修改,以確保下標範圍為0~Max_Size-1。對指標進行取模運算,就能使指標到達最大下標位置後回到0,符合“迴圈”佇列的特點。
因此入隊時隊尾指標加1操作改為: pQueue->tail = (pQueue->tail+1) % MAX_SIZE;
入隊時隊尾指標加1操作改為: pQueue->head = (pQueue->head+1) % MAX_SIZE;
#ifndef QUEUE_H #define QUEUE_H typedef class queue { public: queue(int len = 10); queue(const queue& src); queue operator=(const queue& src); ~queue(); void push(int val); void pop(); int getHead(); bool isEmpty(); bool isFull(); void resize(); void show(); private: int *_arr; int _head; int _tail; int _len; }Queue,*Pqueue; #endif
#include"queue.h"
#include<iostream>
using namespace std;
queue::queue(int len)
{
if (len < 10)
{
len = 10;
}
_arr = new int[len];
_head = 0;
_tail = 0;
_len = len;
}
queue::queue(const queue& src)
{
_arr = new int[src._len];
_len = src._len;
_head = src._head;
_tail = src._tail;
for (int i = _head; i != _tail; i=(i + 1) % _len)
{
_arr[i] = src._arr[i];
}
}
queue queue::operator=(const queue& src)
{
if (this == &src)
{
return *this;
}
if (_arr != NULL)
delete []_arr;
_arr = new int[src._len];
_len = src._len;
_head = src._head;
_tail = src._tail;
for (int i = _head; i != _tail; i=(i + 1) % _len)
{
_arr[i] = src._arr[i];
}
return *this;
}
queue::~queue()
{
if (_arr != NULL)
delete[]_arr;
_arr = NULL;
_len = 0;
_tail = 0;
_head = 0;
}
void queue::push(int val)
{
if (isFull())
{
resize();
}
_arr[_tail] = val;
_tail = (_tail + 1) % _len;
}
void queue::pop()
{
if (isEmpty())
{
return;
}
_head = (_head + 1) % _len;
}
int queue::getHead()
{
if (isEmpty())
{
return -1;
}
return _arr[_head];
}
bool queue::isEmpty()
{
return _tail == _head;
}
bool queue::isFull()
{
return (_tail + 1) % _len == _head;
}
void queue::resize()
{
int len = _len + (_len >> 1);
int *tmp = new int[len];
for (int i = _head, j = 0; i != _tail; i = (i + 1) % _len,j++)
{
tmp[j] = _arr[i];
}
if (_arr !=NULL)
delete[]_arr;
_arr = NULL;
_arr = tmp;
_head = 0;
_tail = _len - 1;
_len = len;
}
void queue::show()
{
for (int i = 0; i < _len; i++)
{
cout << _arr[i] << " ";
}
cout << endl;
cout << "head:" << _head << endl;
cout << "tail:" << _tail << endl;
cout << "len:" << _len << endl;
}
#include"queue.h"
#include<iostream>
using namespace std;
int main()
{
Queue que;
for (int i = 0; i < 9; i++)
{
que.push(i);
}
que.show();
for (int i = 0; i < 3; i++)
{
cout << que.getHead() << endl;
que.pop();
}
que.show();
for (int i = 0; i < 3; i++)
{
que.push(i + 10);
}
que.show();
for (int i = 0; i < 3; i++)
{
que.push(i + 20);
}
que.show();
Queue que1 = que;
que1.show();
Queue que2;
que2 = que1;
que2.show();
return 0;
}