數據結構學習(六)——循環順序隊列的操做

隊列是一種只容許在表的一端(稱爲隊尾)進行插入,而在另外一端(稱爲隊頭)進行刪除的線性表,是線性表的一種特例。node

順序隊列是用數組結構來表示的。爲了描述隊列的這種結構,咱們須要兩個代表隊頭和隊尾的指針,規定隊頭指針指向隊列頭結點的前一個位置,而隊尾指針指向隊列的尾結點。而爲何又會用到循環隊列呢,由於爲了防止「假上溢」對空間形成的浪費。「假上溢」是這麼來的,先說「上溢」和「下溢」。下溢就是當空對時,若是再作出隊操做,則會產生「下溢」。數組

當隊滿時,再作入對操做會產生「上溢」。可是,若是當前尾指針等於數組的上界,即便隊列不滿,再作入隊操做也會引發溢出。這種現象就是「假上溢」。然而有了循環隊列,咱們就能夠避免假上溢的問題了。可是循環隊列仍是有一個問題,就是判斷隊列與隊滿的狀況。若是按照前面的規定,隊頭指針指向隊列頭結點的前一個位置,而隊尾指針指向隊列的尾結點。那麼是分辨不出來隊滿與隊空的關係的。我看書中列出了3種解決此問題的方法。不過第三種最適合,它是採用少用一個節點空間,即頭指針指向的空間不使用。這樣的話。當front等於rear時,隊空;入隊後,當尾指針加1後等於頭指針,即:(rear+1)%maxsize = front.則說明這時隊列已滿。指針

下面是對循環順序隊列操做的一個總體代碼:code

#include <stdio.h>
#include <stdlib.h>

#define MAXSIZE 100

typedef struct node
{
	int data[MAXSIZE];
	int front;			//存放隊列頭地址
	int rear;			//存放隊列尾地址
}sequeue;

void Sequeue_SetNull(sequeue *q);		//隊列置空
int Sequeue_Empty(sequeue *q);			//判斷隊列是否爲空
int Sequeue_GetFront(sequeue *q);		//獲得隊列頭結點
int Sequeue_In(sequeue *q, int dat);	//入對操做
int Sequeue_Out(sequeue *q);			//出隊操做
void ShowSequeue(sequeue *q);			//輸出顯示隊列

int main(void)
{
	int num, i, dat, choice, ans;
	sequeue *q;

	q = (sequeue*)malloc(sizeof(sequeue));

	printf("循環順序隊列的操做練習:\n");
	printf("輸入你想建立隊列的數據個數:\n");
	scanf("%d", &num);
	if(num>MAXSIZE-1)
	{
		printf("隊列結點數大於最大容許空間!\n");
		return 0;
	}
	Sequeue_SetNull(q);	
	printf("請依次輸入隊列數據:\n");
	for(i=1; i<num+1; i++)			//循環輸入隊列結點數據
	{
		scanf("%d", &dat);
		q->data[i] = dat;
		q->rear = i;
	}
	while(1)
	{
		printf("隊列操做:\n");
		printf("1.取隊列結點\n");
		printf("2.入隊操做\n");
		printf("3.出隊操做\n");
		printf("4.輸出隊列\n");
		printf("5.退出程序\n");
		printf("作出選擇:\n");
		scanf("%d", &choice);

		switch(choice)
		{
		//取隊列頭結點
		case 1:
			dat = Sequeue_GetFront(q);
			printf("頭結點爲:%d\n", dat);
			break;
		//入隊
		case 2:
			printf("輸入你想入隊的數據:\n");
			scanf("%d", &dat);
			ans = Sequeue_In(q, dat);
			if(ans)
				printf("入隊成功!\n");
			else
				printf("入隊失敗!\n");
			break;
		//出隊
		case 3:
			ans = Sequeue_Out(q);
			if(ans)
				printf("出隊成功!\n");
			else
				printf("出隊失敗!\n");
			break;
		//輸出顯示隊列
		case 4:
			ShowSequeue(q);
			break;
		//退出程序
		case 5:
			return 0;
			break;
		default:
			printf("選擇無效!\n");
			break;
		}
	}
}	

//隊列置空
void Sequeue_SetNull(sequeue *q)
{
	q->rear = 0;				//其中數組第一個節點空間不使用(即下標爲0數組元素),用做隊列滿與空的區別
	q->front = 0;					
}

//判斷隊列是否爲空
int Sequeue_Empty(sequeue *q)
{
	if(q->front == q->rear)		//頭結點等於尾結點即表示隊列爲空
		return 1;
	else
		return 0;
}

//取得隊列頭結點
int Sequeue_GetFront(sequeue *q)
{
	if(Sequeue_Empty(q))		//取頭結點先要判斷隊列是否爲空
	{
		printf("隊列空!\n");
		return 0;
	}
	else
		return q->data[(q->front+1) % MAXSIZE];
}

//入隊
int Sequeue_In(sequeue *q, int dat)
{
	if((q->rear+1)%MAXSIZE == q->front)				//入隊先要判斷隊列是否已經滿了
		return 0;
	else
	{
		q->rear = (q->rear+1) % MAXSIZE;			//使用求模運算
		q->data[q->rear]= dat;
		return 1;
	}
}

//出隊
int Sequeue_Out(sequeue *q)
{
	if(Sequeue_Empty(q))				//出隊先要判斷隊列是否爲空
		return 0;
	else
	{
		q->front = (q->front+1) % MAXSIZE;		//求模運算
		return q->data[q->front];
	}
}

//輸出顯示隊列
void ShowSequeue(sequeue *q)
{
	int i;

	i = q->front+1;
	while(i != q->rear+1)
	{
		printf("%d ", q->data[i]);
		i++;
	}
	printf("\n");
}
相關文章
相關標籤/搜索