1. 程式人生 > >C++實現佇列(迴圈佇列)

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;
}