隊(duì)列具有新進(jìn)先出(FIFO)的特點(diǎn).
1 隊(duì)列的順序結(jié)構(gòu)
1.1 數(shù)據(jù)結(jié)構(gòu)
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 10
typedef int QElemType;
typedef int Status;
typedef struct {
int data[MAXSIZE]; // 存放數(shù)據(jù)的數(shù)組
int front; // 隊(duì)首索引
int rear; // 隊(duì)尾索引
}SqQueue;
1.2 入棧和出棧的實(shí)現(xiàn)
假設(shè)一個(gè)可以容納5個(gè)元素的隊(duì)列,如下:
{ x, x, x, x, x }
^
front
rear
我們使用 x 表示這個(gè)位置還沒有插入任何元素.
此時(shí)隊(duì)列的front 和 rear 都為0。
我們將元素1 2 3 和 4 依次入隊(duì),那么現(xiàn)在隊(duì)列中的內(nèi)容如下:
{ 1, 2, 3, 4, x }
^ ^
front rear
現(xiàn)在front為0, rear為4, 接下來我們將 1 和 2 出隊(duì),隊(duì)列內(nèi)容為:
{ x, x, 3, 4, x }
^ ^
front rear
接著,我們將元素5 6依次入隊(duì),當(dāng)元素6入隊(duì)時(shí),就會(huì)出現(xiàn)溢出,實(shí)際上隊(duì)列中還有3個(gè)空位,但是現(xiàn)在只能入隊(duì)1個(gè)元素,這里的溢出我們稱之為假溢出。
為了解決假溢出,將隊(duì)列的空間進(jìn)行充分的利用,這里我們可以引入了一個(gè)循環(huán)隊(duì)列的概念,當(dāng)隊(duì)尾索引等于數(shù)組的最大索引時(shí),當(dāng)下一個(gè)元素入隊(duì)時(shí),我們從數(shù)組的索引為0的位置開始入隊(duì)。那么現(xiàn)在將元素5 6入隊(duì)后,隊(duì)列的內(nèi)容如下:
{ 6, x, 3, 4, 5 }
^ ^
rear front
這樣就能將充分的將空間利用起來, 但是現(xiàn)在又存在一個(gè)問題,如果我們繼續(xù)入隊(duì)元素7后:
{ 6, 7, 3, 4, 5 }
^
front
rear
這里隊(duì)首索引和隊(duì)尾索引又相等了,這時(shí)我們將無法區(qū)分隊(duì)列為空和隊(duì)列滿的時(shí)候。因此當(dāng)隊(duì)列中只有一個(gè)空位時(shí),我們就認(rèn)為隊(duì)列滿了,不能繼續(xù)入隊(duì),這樣隊(duì)列滿的時(shí)候他們首尾索引就不相等了。
{ 6, x, 3, 4, 5 }
^ ^
rear front
1.3 代碼實(shí)現(xiàn)
// 1.初始隊(duì)列
Status initQueue(SqQueue *Q) {
Q->front = 0;
Q->rear = 0;
return OK;
}
// 2.隊(duì)列清空
Status clearQueue(SqQueue *Q) {
Q->front = 0;
Q->rear = 0;
return OK;
}
// 3.隊(duì)列是否為空
Status queueEmpey(SqQueue Q) {
return Q.rear == Q.front;
}
// 4.隊(duì)列的長度
int queueLength(SqQueue Q) {
return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
}
// 5.獲取隊(duì)列的頭部
Status getQueueHead(SqQueue Q, QElemType *e) {
if (Q.rear == Q.front) return ERROR;
*e = Q.data[Q.front];
return OK;
}
// 6.入隊(duì)
Status enqueue(SqQueue *Q, QElemType e) {
if ((Q->rear + 1) % MAXSIZE == Q->front) return ERROR;
Q->data[Q->rear] = e;
Q->rear = (Q->rear + 1) % MAXSIZE;
return OK;
}
// 7.出隊(duì)
Status dequeue(SqQueue *Q, QElemType *e) {
if (Q->front == Q->rear) return ERROR;
*e = Q->data[Q->front];
Q->front = (Q->front + 1) % MAXSIZE;
return OK;
}
// 遍歷
void queueTraverse(SqQueue Q) {
int i = Q.front;
while (i != Q.rear) {
printf("%d ", Q.data[i]);
i = (i + 1) % MAXSIZE;
}
printf("\n");
}
int main(int argc, const char * argv[]) {
// insert code here...
SqQueue Q;
QElemType e;
if (initQueue(&Q)) {
printf("初始化隊(duì)列成功\n");
}
for (int i = 0; i < 10; i++) {
enqueue(&Q, i);
}
printf("隊(duì)列中的元素為:");
queueTraverse(Q);
printf("隊(duì)列的長度為:%d\n", queueLength(Q));
dequeue(&Q, &e);
printf("獲取出隊(duì)元素:%d\n", e);
printf("隊(duì)列中的元素為:");
queueTraverse(Q);
getQueueHead(Q, &e);
printf("獲取隊(duì)列頭部:%d\n", e);
printf("隊(duì)列是否為空:%d\n", queueEmpey(Q));
printf("清空隊(duì)列\(zhòng)n");
clearQueue(&Q);
printf("隊(duì)列是否為空:%d\n", queueEmpey(Q));
printf("隊(duì)列中的元素為:");
queueTraverse(Q);
printf("隊(duì)列的長度為:%d\n", queueLength(Q));
return 0;
}
//輸出:
//初始化隊(duì)列成功
//隊(duì)列中的元素為:0 1 2 3 4 5 6 7 8
//隊(duì)列的長度為:9
//獲取出隊(duì)元素:0
//隊(duì)列中的元素為:1 2 3 4 5 6 7 8
//獲取隊(duì)列頭部:1
//隊(duì)列是否為空:0
//清空隊(duì)列
//隊(duì)列是否為空:1
//隊(duì)列中的元素為:
//隊(duì)列的長度為:0
2 隊(duì)列的鏈?zhǔn)浇Y(jié)構(gòu)
使用順序儲(chǔ)存結(jié)構(gòu)時(shí),會(huì)出現(xiàn)假溢出問題,因此我們引入循環(huán)隊(duì)列的概念來解決假溢出問題,這樣的話如果隊(duì)列滿了,要將隊(duì)列進(jìn)行擴(kuò)容時(shí),將會(huì)變得十分復(fù)雜。如果我們使用鏈?zhǔn)浇Y(jié)構(gòu)來實(shí)現(xiàn)隊(duì)列的話就沒有上面的問題。
2.1 數(shù)據(jù)結(jié)構(gòu)
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int QElemType;
typedef int Status;
typedef struct QNode {
QElemType data;
struct QNode *next;
}QNode, *QNodePtr;
typedef struct {
QNodePtr front;
QNodePtr rear;
int count;
} LinkQueue;
2.2 代碼實(shí)現(xiàn)
// 1.初始化
Status initQueue(LinkQueue *Q) {
if (Q == NULL) return ERROR;
// 初始化頭結(jié)點(diǎn)
Q->rear = Q->front = (QNodePtr)malloc(sizeof(QNode));
if (Q->front == NULL) return ERROR;
Q->front->next = NULL;
Q->count = 0;
return OK;
}
// 2.銷毀隊(duì)列
Status destoryQueue(LinkQueue *Q) {
if (!Q) return ERROR;
// 從頭結(jié)點(diǎn)開始依次釋放結(jié)點(diǎn)
while (Q->front) {
Q->rear = Q->front->next;
Q->front = Q->front->next;
free(Q->rear);
}
Q->count = 0;
return OK;
}
// 3.清空隊(duì)列
Status clearQueue(LinkQueue *Q) {
if (!Q) return ERROR;
// 保留頭結(jié)點(diǎn),釋放其余結(jié)點(diǎn)
QNodePtr p, q;
// 指向首元結(jié)點(diǎn)
p = Q->front->next;
while (p) {
q = p;
p = p->next;
free(q);
}
Q->front->next = NULL;
Q->rear = Q->front;
Q->count = 0;
return OK;
}
// 4.隊(duì)列是否為空
Status queueEmpty(LinkQueue Q) {
return Q.front == Q.rear;
}
// 5.獲取隊(duì)列的長度
int queueLength(LinkQueue Q) {
return Q.count;
}
// 6.獲取隊(duì)頭
Status getQueueHead(LinkQueue Q, QElemType *e) {
*e = Q.front->next->data;
return OK;
}
// 7.入隊(duì)
Status enqueue(LinkQueue *Q, QElemType e) {
if (!Q) return ERROR;
QNodePtr p = (QNodePtr)malloc(sizeof(QNode));
if (!p) return ERROR;
p->next = NULL;
p->data = e;
Q->rear->next = p;
Q->rear = p;
Q->count++;
return OK;
}
// 8.出隊(duì)
Status dequeue(LinkQueue *Q, QElemType *e) {
if (!Q) return ERROR;
if (Q->count == 0) return ERROR;
// 獲取隊(duì)頭結(jié)點(diǎn)的值
*e = Q->front->next->data;
// 獲取隊(duì)頭結(jié)點(diǎn)
QNodePtr p = Q->front->next;
Q->front->next = p->next;
free(p);
Q->count--;
// 刪空后,將隊(duì)尾指向頭結(jié)點(diǎn)
if (Q->count == 0) Q->rear = Q->front;
return OK;
}
// 9.遍歷
void queueTraverse(LinkQueue Q) {
QNodePtr p = Q.front->next;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main(int argc, const char * argv[]) {
// insert code here...
LinkQueue q;
int e;
if (initQueue(&q)) {
printf("隊(duì)列初始化成功\n");
}
for (int i = 0; i < 10; i++) {
enqueue(&q, i);
}
printf("隊(duì)列中的元素為:");
queueTraverse(q);
printf("隊(duì)列的長度為: %d\n", queueLength(q));
printf("隊(duì)列是否為空: %d\n", queueEmpty(q));
dequeue(&q, &e);
printf("出隊(duì)元素為: %d\n", e);
getQueueHead(q, &e);
printf("獲取隊(duì)頭: %d\n", e);
printf("隊(duì)列中的元素為:");
queueTraverse(q);
printf("隊(duì)列的長度為: %d\n", queueLength(q));
printf("隊(duì)列是否為空: %d\n", queueEmpty(q));
clearQueue(&q);
printf("隊(duì)列中的元素為:");
queueTraverse(q);
printf("隊(duì)列的長度為: %d\n", queueLength(q));
printf("隊(duì)列是否為空: %d\n", queueEmpty(q));
destoryQueue(&q);
return 0;
}
輸出:
隊(duì)列初始化成功
隊(duì)列中的元素為:0 1 2 3 4 5 6 7 8 9
隊(duì)列的長度為: 10
隊(duì)列是否為空: 0
出隊(duì)元素為: 0
獲取隊(duì)頭: 1
隊(duì)列中的元素為:1 2 3 4 5 6 7 8 9
隊(duì)列的長度為: 9
隊(duì)列是否為空: 0
隊(duì)列中的元素為:
隊(duì)列的長度為: 0
隊(duì)列是否為空: 1