隊列

隊列:只允許在一端進行插入數據操作,在另一端進行刪除數據操作的特殊線性表

進行插入操作的一端稱爲隊尾(入隊列),進行刪除操作的一端稱爲隊頭(出隊列)

隊列最大的特點就是:先進先出,後進後出

隊列可分爲順序隊列、循環隊列、鏈式隊列

1)順序隊列放在線性表中,有兩種情況:

隊頭不動,出隊列時隊頭後的所有元素向前移動(缺陷:出隊搬移數據會比較繁瑣)

對頭移動,出隊時隊頭向後移動一個位置(缺陷:會出現假溢出的問題)

擴充:假溢出指的是實際上是有空間存放數據的,可根據判斷卻認爲沒有空間

2)循環隊列解決了假溢出的問題(也就是上面的rear到5了之後還可以回到0的位置)

擴充:可是現在剛解決了一個問題又出現另外一個問題,循環隊列如何得知隊列的空和滿呢?兩種情況如何區分??

有才的人類想到三個辦法:少用一個存儲單元;設置一個標記位;設置一個計數器

3)鏈式隊列(上面兩種空間的大小畢竟是死的,存放數據總有放滿的時候,再存就會溢出)

鏈式隊列是一種特殊的單鏈表,只在單鏈表上進行頭刪和尾插操作

 

在此我使用鏈式隊列(操作相對簡單^0^)

typedef int qDataType;

//結點中含有數據和指向下一個結點的指針
typedef struct qNode
{
	qDataType data;
	struct qNode *pNext;
}qNode;

//隊列中含有指向鏈表頭和尾的兩個指針和隊列中元素的個數
typedef struct queue
{
	qNode *pFront;
	qNode *pRear;
	int size;
}queue;

在隊列中我實現了以下的基本操作

//隊列的初始化
void queueInit(queue *pQ);

//隊列的銷燬
void queueDestroy(queue *pQ);

//隊列數據的打印
void queuePrintf(queue pQ);

//入隊操作
void queuePush(queue *pQ, qDataType data);

//出隊操作
void queuePop(queue *pQ);

//隊首元素
qDataType queueFront(queue *pQ);

//是否爲空隊列
int queueIsEmpty(queue *pQ);

//隊列的大小
int queueSize(queue *pQ);

1)初始化

void queueInit(queue *pQ)
{
	assert(pQ != NULL);
	//初始化隊列沒有數據結點
	pQ->pFront = NULL;
	pQ->pRear = NULL;
	pQ->size = 0;
}

2)銷燬

void queueDestroy(queue *pQ)
{
	assert(pQ);
	qNode *node;
	while (pQ->pFront != NULL)
	{
		node = pQ->pFront;
		pQ->pFront = pQ->pFront->pNext;
		free(node);
	}
	pQ->pFront = NULL;
	pQ->pRear = NULL;
	pQ->size = 0;
}

3)打印

void queuePrintf(queue pQ)
{
	while (pQ.pFront != NULL)
	{
		printf("%d->", pQ.pFront->data);
		pQ.pFront = pQ.pFront->pNext;
	}
	printf("NULL\n");
}

#if 0
void queuePrintf(queue *pQ)
{
	assert(pQ != NULL);
	qNode *node = pQ->pFront;
	while (node != NULL)
	{
		printf("%d->", node->data);
		node = node->pNext;
	}
	printf("NULL\n");
}
#endif

4)入隊

void queuePush(queue *pQ, qDataType data)
{
	assert(pQ != NULL);
	qNode *newNode = (qNode *)malloc(sizeof(qNode));
	assert(newNode);
	newNode->data = data;
	newNode->pNext = NULL;
	pQ->size++;
	//當前鏈表中無結點
	if (pQ->pFront == NULL)
	{
		pQ->pFront = newNode;
		pQ->pRear = newNode;
		return;
	}
	pQ->pRear->pNext = newNode;
	pQ->pRear = newNode;
}

5)出隊

void queuePop(queue *pQ)
{
	assert(pQ != NULL);
	assert(pQ->size > 0);
	qNode *node = pQ->pFront;
	pQ->size--;
	//當前只有一個結點
	if (pQ->pFront == pQ->pRear)
	{
		free(node);
		pQ->pFront = NULL;
		pQ->pRear = NULL;
		return;
	}
	pQ->pFront = pQ->pFront->pNext;
	free(node);
}

6)隊首

qDataType queueFront(queue *pQ)
{
	assert(pQ != NULL);
	assert(pQ->size > 0);
	return pQ->pFront->data;
}

7)判空

int queueIsEmpty(queue *pQ)
{
	assert(pQ != NULL);
	return pQ->size == 0 ? 1 : 0;
}

8)大小

int queueSize(queue *pQ)
{
	assert(pQ != NULL);
	return pQ->size;
}

總結:瞭解了之間單鏈表博客的內容後,相信對隊列的操作就容易多了。因爲我們只能一邊出一邊入

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章