數據結構——隊列

1、隊列概念前端

隊列時一種特殊的線性表,只容許在表的前端進行刪除操做,而在表的後端進行插入操做,隊列具備先進先出的特色。後端

隊列的操做很簡單,主要有如下幾種常見的操做:指針

(1)初始化隊列:建立一個隊列code

(2)進隊列:將一個元素添加到隊尾隊列

(3)出隊列:將隊頭元素取出,同時刪除該元素,使下一個元素成爲對頭內存

(4)獲取隊列第一元素:將隊頭元素取出,不刪除該元素it

(5)獲取隊列長度:根據隊頭和隊尾計算出隊列中元素的數量class

 

2、順序隊列實現循環

    將隊列用順序存儲方式保存時,在內存中申請一片區域用來保存元素,當第一個元素A進入隊列時,因是空列隊,所以元素A將排在隊頭,接着B、C、D順次進入隊列,就獲得如圖所示的隊列。其中head指向隊頭,以指示隊頭元素出隊操做,tail指向隊尾,以指示新增元素進入隊列。以下圖所示:im


    執行一次出隊操做,元素A將出隊,這時第2個元素B將成爲隊頭,head指針將指向該元素若是要將元素E入隊,則是將其放入tail指針指向元素的後一個位置(以下圖爲5的單元),並使tail指針指向序號爲5的單元。

(1)定義順序隊列的結構

#define QUEUEMAX 15

typedef struct{
	DATA data[QUEUEMAX];
	int head;
	int tail;
} SeqQueue;

(2)初始化隊列

SeqQueue *SeqQueueInit()
{
	SeqQueue *q;
	if (q=(SeqQueue *)malloc(sizeof(SeqQueue))) {
		q->head = 0;
		q->tail = 0;
		return q;
	}

	return NULL;
}

(3)釋放隊列

void SeqQueueFree(SeqQueue *q)
{
	if (q)
		free(q);
}

(4)獲取隊列狀態

/*
*判斷隊列是否爲空
*/

int SeqQueueIsEmpty(SeqQueue *q)
{
	return (q->head == q->tail);
}

/*
*判斷隊列是否已滿
*/
int SeqQueueIsFull(SeqQueue *q)
{
	return (q->tail == QUEUEMAX);
}

/*
*獲取隊列的長度
*/
int SeqQueueLen(SeqQueue *q)
{
	return (q->tail - q->head);
}

(5)入隊操做

int SeqQueueIn(SeqQueue *q, DATA data)
{
	if (SeqQueueIsFull(q)) {
		printf("隊列已滿!\n");
		return 0;
	}

	q->data[q->tail++] = data;
	return 1;
}

(6)出隊操做

DATA *SeqQueueOut(SeqQueue *q)
{
	if (SeqQueueIsEmpty(q)) {
		printf("隊列已空!\n");
		return NULL;
	}

	return &(q->data[q->head++]);
}

(7)獲取隊頭元素

DATA *SeqQueuePeek(SeqQueue *q)
{
	if (SeqQueueIsEmpty(q)) {
		printf("隊列已空!\n");
		return NULL;
	}

	return &(q->data[q->head]);
}

3、循環隊列

    因爲每次出隊後,隊頭的指針都向後移動,這時候就會出現一個問題,就是假溢出。以下圖所示:

tail已指向隊尾,這時進行入隊操做時,雖然前面還有空位置,但仍然顯示隊列已滿。爲了解決這個問題,就提出了循環隊列。

循環隊列就是將隊列的首尾相連構成一個環形區域,當在第n個位置進行元素的入隊操做後,下一個地址就翻轉爲1

循環隊列結構圖:

在循環隊列中,主要須要計算隊尾tail和隊頭head的序號

以入隊操做爲例:

一、將隊尾序號加1,即tail=tail+1

二、若tail=n+1,則tail=1

其實前2步,可使用表達式tail=(tail+1)%n

三、若head=tail,即隊尾和隊頭重合了,表示隊列已滿提示隊列溢出

四、若未溢出,將元素入隊便可

(1)定義循環隊列的結構 

#define QUEUEMAX 15

typedef struct{
	DATA data[QUEUEMAX];
	int head;
	int tail;
} CycQueue;

(2)初始化隊列

CycQueue *CycQueueInit()
{
	CycQueue *q;
	if (q=(CycQueue *)malloc(sizeof(CycQueue))) {
		q->head = 0;
		q->tail = 0;
		return q;
	}

	return NULL;
}

(3)釋放隊列

void CycQueueFree(CycQueue *q)
{
	if (q)
		free(q);
}

(4)獲取隊列狀態

/*
*判斷隊列是否爲空
*/

int CycQueueIsEmpty(CycQueue *q)
{
	return (q->head == q->tail);
}


/*
*判斷隊列是否已滿
*/
int CycQueueIsFull(CycQueue *q)
{
	return ((q->tail+1)%QUEUEMAX == q->head);
}


/*
*獲取隊列的長度
*/
int CycQueueLen(CycQueue *q)
{
	int n;
	n = q->tail - q->head;
	if (n < 0) {
		n = QUEUEMAX + n;
	}
	return n;
}

(5)入隊操做

int CycQueueIn(CycQueue *q, DATA data)
{
	if (CycQueueIsFull(q)) {
		printf("隊列已滿!\n");
		return 0;
	}
	q->tail = (q->tail+1)%QUEUEMAX;
	q->data[q->tail] = data;
	return 1;
}

(6)出隊操做

DATA *CycQueueOut(CycQueue *q)
{
	int head;

	if (CycQueueIsEmpty(q)) {
		printf("隊列已空!\n");
		return NULL;
	}

	head = q->head;
	q->head = (q->head +1)%QUEUEMAX;
	return &(q->data[head]);
}

(7)獲取隊頭元素

DATA *CycQueuePeek(CycQueue *q)
{
	if (CycQueueIsEmpty(q)) {
		printf("隊列已空!\n");
		return NULL;
	}
	return &(q->data[q->head]);
}