隊列:只允許在一端進行插入數據操作,在另一端進行刪除數據操作的特殊線性表
進行插入操作的一端稱爲隊尾(入隊列),進行刪除操作的一端稱爲隊頭(出隊列)
隊列最大的特點就是:先進先出,後進後出
隊列可分爲順序隊列、循環隊列、鏈式隊列
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;
}
總結:瞭解了之間單鏈表博客的內容後,相信對隊列的操作就容易多了。因爲我們只能一邊出一邊入