像栈一样,队列也是表。然而,使用队列时插入在一段进行而删除则在另一端进行。队列的基本操作是Enqueue(入队),它是在表的末端(叫做队尾(rear))插入一个元素,还有Dequeue(出队),它是删除(或返回)在表的开头(叫做队头(front))的元素。通过数组和链表都可以实现队列,其中数组更普遍一点。
在考虑数组实现时,由于数组的大小是有限的,为了操作更多的元素,我们可以用循环数组实现,即只要Front或Rear到达数组的尾端,它又绕回到开头。在考虑队列的循环实现,有两件事情要警惕,一是检测队列是否为空很重要的,因为空时一次Dequeue操作返回一个不确定的值。二是某些程序设计人员使用不同的方法来表示队列和队尾。目前比较普遍的有三种方法:
其一是使用一个计数器记录队列中元素的总数(实际上是队列长度)。
其二是少用一个元素的空间,约定入队前,测试尾指针在循环意义下加1后是否等于头指针,若相等则认为队满(注意:rear所指的单元始终为空);
其三是另设一个布尔变量以匹别队列的空和满;
1. 循环数组实现。添加一个计数器记录队列中元素的总数
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct QueueRecord *Queue;
Queue createQueue(int MaxElements);
void disposeQueue(Queue Q);
void enqueue(ElementType X, Queue Q);
ElementType dequeue(Queue Q);
struct QueueRecord
{
int Capacity;
int Size;
int Front;
int Rear;
ElementType *Array;
};
Queue createQueue(int MaxElements)
{
Queue Q;
Q = (Queue)malloc(sizeof(QueueRecord));
if(Q == NULL)
return NULL;
Q->Array = (ElementType *)malloc(MaxElements * sizeof(ElementType));
if(Q->Array == NULL)
return NULL;
Q->Capacity = MaxElements;
Q->Size = 0;
Q->Front = 0;
Q->Rear = -1;
return Q;
}
void disposeQueue(Queue Q)
{
if(Q != NULL)
{
free(Q->Array);
free(Q);
}
return;
}
void enqueue(ElementType X, Queue Q)
{
if(Q->Size >= Q->Capacity) //队列已满
return;
if(++Q->Rear == Q->Capacity) //假溢出
Q->Rear = 0;
Q->Size++;
Q->Array[Q->Rear] = X;
return;
}
ElementType dequeue(Queue Q)
{
if(Q->Size == 0)
return 0;
Q->Size--;
int tmp = Q->Front;
Q->Front = (Q->Front + 1) % Q->Capacity;
return Q->Array[tmp];
}
//循环打印
void printQueue(Queue Q)
{
int Rear;
if(Q == NULL || Q->Size == 0)
return;
Rear = Q->Rear;
if(Q->Front > Rear)
Rear += Q->Capacity;
for(int i = Q->Front;i <= Rear; ++i)
{
if(i >= Q->Capacity)
printf("%d", Q->Array[i - Q->Capacity]);
else
printf("%d", Q->Array[i]);
}
printf("\n");
return;
}
int main()
{
Queue Q;
Q = createQueue(10);
if(Q == NULL)
return 0;
enqueue(9, Q);
printf("%d\n", dequeue(Q));
for(int i=0; i<10; ++i)
{
enqueue(i, Q);
}
printQueue(Q);
printf("%d\n", dequeue(Q));
printQueue(Q);
enqueue(9, Q);
enqueue(9, Q);
printQueue(Q);
disposeQueue(Q);
system("pause");
return 0;
}
2. 循环数组实现。少用一个元素的空间,约定入队前,测试尾指针在循环意义下加1后是否等于头指针,若相等则认为队满(注意:rear所指的单元始终为空)
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct QueueRecord *Queue;
Queue createQueue(int MaxElements);
void disposeQueue(Queue Q);
void enqueue(ElementType X, Queue Q);
ElementType dequeue(Queue Q);
struct QueueRecord
{
int Capacity;
int Front;
int Rear;
ElementType *Array;
};
Queue createQueue(int MaxElements)
{
Queue Q;
Q = (Queue)malloc(sizeof(QueueRecord));
if(Q == NULL)
return NULL;
Q->Array = (ElementType *)malloc(MaxElements * sizeof(ElementType));
if(Q->Array == NULL)
return NULL;
Q->Capacity = MaxElements;
Q->Front = 0;
Q->Rear = 0;
return Q;
}
void disposeQueue(Queue Q)
{
if(Q != NULL)
{
free(Q->Array);
free(Q);
}
return;
}
void enqueue(ElementType X, Queue Q)
{
int rear;
rear = (Q->Rear+1) % Q->Capacity;
if(rear == Q->Front)
return;
Q->Array[Q->Rear] = X;
Q->Rear = rear;
return;
}
ElementType dequeue(Queue Q)
{
if(Q->Front == Q->Rear)
return 0;
int tmp = Q->Front;
Q->Front = (Q->Front + 1) % Q->Capacity;
return Q->Array[tmp];
}
void printQueue(Queue Q)
{
int Rear;
if(Q == NULL || Q->Front == Q->Rear)
return;
Rear = Q->Rear;
if(Q->Front > Rear)
Rear += Q->Capacity;
for(int i = Q->Front;i < Rear; ++i)
{
if(i >= Q->Capacity)
printf("%d", Q->Array[i - Q->Capacity]);
else
printf("%d", Q->Array[i]);
}
printf("\n");
return;
}
int main()
{
Queue Q;
Q = createQueue(10);
if(Q == NULL)
return 0;
enqueue(9, Q);
printf("%d\n", dequeue(Q));
for(int i=0; i<10; ++i)
{
enqueue(i, Q);
}
printQueue(Q);
printf("%d\n", dequeue(Q));
printQueue(Q);
enqueue(9, Q);
enqueue(9, Q);
printQueue(Q);
disposeQueue(Q);
system("pause");
return 0;
}
3. 单链表实现。
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct Node *PtrToNode;
typedef struct QueueRecord *Queue;
Queue createQueue();
void disposeQueue(Queue Q);
void enqueue(ElementType X, Queue Q);
ElementType dequeue(Queue Q);
struct QueueRecord
{
PtrToNode Front;
PtrToNode Rear;
};
struct Node
{
ElementType Element;
PtrToNode Next;
};
Queue createQueue()
{
PtrToNode head;
head = (PtrToNode)malloc(sizeof(struct Node));
if(head == NULL)
return NULL;
head->Next = NULL;
Queue q;
q = (Queue)malloc(sizeof(struct QueueRecord));
if(q == NULL)
return NULL;
q->Front = head;
q->Rear = head;
return q;
}
void disposeQueue(Queue Q)
{
PtrToNode p;
PtrToNode tmp;
if(Q == NULL || Q->Front == NULL)
return;
p = Q->Front->Next;
free(Q->Front);
free(Q);
while(p != NULL)
{
tmp = p;
p = p->Next;
free(tmp);
}
return;
}
void enqueue(ElementType X, Queue Q)
{
PtrToNode tmp;
tmp = (PtrToNode)malloc(sizeof(struct Node));
if(tmp == NULL)
return;
tmp->Element = X;
tmp->Next = NULL;
Q->Rear->Next = tmp;
Q->Rear = tmp;
return;
}
ElementType dequeue(Queue Q)
{
PtrToNode tmp;
if(Q == NULL || Q->Front == NULL || Q->Front->Next == NULL)
return 0;
tmp = Q->Front->Next;
Q->Front->Next = tmp->Next;
if(tmp == Q->Rear)
Q->Rear = Q->Front;
ElementType x = tmp->Element;
free(tmp);
return x;
}
void printQueue(Queue Q)
{
PtrToNode p;
if(Q == NULL || Q->Front == NULL || Q->Front->Next == NULL)
return;
p = Q->Front->Next;
while(p != NULL)
{
printf("%d", p->Element);
p = p->Next;
}
printf("\n");
return;
}
int main()
{
Queue Q;
Q = createQueue();
if(Q == NULL)
return 0;
enqueue(1, Q);
printf("%d\n", dequeue(Q));
printf("%d\n", dequeue(Q));
for(int i =0; i < 10; ++i)
enqueue(i, Q);
printQueue(Q);
printf("%d\n", dequeue(Q));
printQueue(Q);
enqueue(9, Q);
printQueue(Q);
disposeQueue(Q);
system("pause");
return 0;
}
队列主要的应用在于排队论。