队列的实现
队列实现跟栈相似,有两种实现方式,一种是用链表实现,一种使用数组实现。为了使这两种实现方法具有相同的函数接口,将函数的原型声明放到queue.h文件中。
编译环境:Visual Studio 2010
fatal.h用于定义错误处理方法
#include <stdio.h>
#include <stdlib.h>
#define FatalError(str) fprintf(stderr, "%s\n", str),exit(1)
queue.h用于声明队列的函数原型
#ifndef QUEUE_H
#define QUEUE_H
typedef int ElementType;
struct QueueRecord;
typedef struct QueueRecord *Queue;
Queue CreateQueue(void);
void DestoryQueue(Queue Q);
void ClearQueue(Queue Q);
int QueueLength(Queue Q);
int IsEmpty(Queue Q);
int IsFull(Queue Q);
ElementType Head(Queue Q);
ElementType Dequeue(Queue Q);
void Enqueue(ElementType X, Queue Q);
#endif
1. 队列的链式实现
链式实现可以有头结点也可以没有头节点,我在这里的实现方式是没有头节点的。如下图所示
queue.c队列的具体实现
#include "fatal.h"
#include "queue.h"
struct Node
{
ElementType Data;
struct Node *Next;
};
typedef struct Node *PtrToNode;
struct QueueRecord
{
PtrToNode Front;//队头指针
PtrToNode Rear; //队尾指针
};
Queue CreateQueue(void)
{
Queue Q;
Q = (Queue)malloc(sizeof(struct QueueRecord));
if(Q == NULL)
FatalError("Out of space");
Q->Front = Q->Rear = NULL;
return Q;
}
void DestoryQueue(Queue Q)
{
PtrToNode TmpCell;
while(Q->Front)
{
TmpCell = Q->Front->Next;
free(Q->Front);
Q->Front = TmpCell;
}
free(Q);
}
void ClearQueue(Queue Q)
{
PtrToNode P, TmpCell;
P = Q->Front;
Q->Front = NULL;
Q->Rear = Q->Front;
while(P)
{
TmpCell = P->Next;
free(P);
P = TmpCell;
}
}
int QueueLength(Queue Q)
{
int cnt = 0;
PtrToNode P;
P = Q->Front;
while(P)
{
++cnt;
P = P->Next;
}
return cnt;
}
int IsEmpty(Queue Q)
{
return Q->Front == NULL;
}
int IsFull(Queue Q)
{
return 0;
}
ElementType Head(Queue Q)
{
return IsEmpty(Q) ? -1 : Q->Front->Data;
}
ElementType Dequeue(Queue Q)
{
ElementType X = -1;
PtrToNode TmpCell;
if(!IsEmpty(Q))
{
TmpCell = Q->Front;
Q->Front = TmpCell->Next;
X = TmpCell->Data;
if(TmpCell == Q->Rear)
Q->Rear = Q->Front;
free(TmpCell);
}
return X;
}
void Enqueue(ElementType X, Queue Q)
{
PtrToNode TmpCell;
TmpCell = (PtrToNode)malloc(sizeof(struct Node));
if(TmpCell == NULL)
FatalError("Out of space");
TmpCell->Data = X;
TmpCell->Next = NULL;
if(IsEmpty(Q))//如果此前为空队列,插入新元素后要求头结点的位置
{
Q->Front = TmpCell;
Q->Rear = TmpCell;
}
else
Q->Rear->Next = TmpCell;
Q->Rear = TmpCell;
}
2. 队列的数组实现
预留数组中的一个空间用来判断队列是否已满。数组实现的是循环队列,如下图所示
queue.c队列的数组实现
#include "fatal.h"
#include "queue.h"
#define MAXQSIZE 100
struct QueueRecord
{
ElementType *Array;
int Front;
int Rear;
int Capacity;
};
Queue CreateQueue(void)
{
Queue Q;
Q = (Queue)malloc(sizeof(struct QueueRecord));
if(Q == NULL)
FatalError("Out of space");
Q->Array = (ElementType *)malloc(sizeof(ElementType) * MAXQSIZE);
if(Q->Array == NULL)
FatalError("Out of space");
Q->Front = 0;
Q->Rear = 0;
Q->Capacity = MAXQSIZE;
return Q;
}
void DestoryQueue(Queue Q)
{
free(Q->Array);
free(Q);
}
void ClearQueue(Queue Q)
{
Q->Front = Q->Rear = 0;
}
int QueueLength(Queue Q)
{
return (Q->Rear - Q->Front + Q->Capacity) % Q->Capacity;
}
int IsEmpty(Queue Q)
{
return Q->Front == Q->Rear;
}
int IsFull(Queue Q)
{
return (Q->Rear + 1) % Q->Capacity == Q->Front;
}
ElementType Head(Queue Q)
{
ElementType X;
if(IsEmpty(Q))
FatalError("Empty queue");
return Q->Array[Q->Front];
}
void Enqueue(ElementType X, Queue Q)
{
if(IsFull(Q))
FatalError("Out of space");
Q->Array[Q->Rear] = X;
Q->Rear = (Q->Rear + 1) % Q->Capacity;
}
ElementType Dequeue(Queue Q)
{
ElementType X;
if(IsEmpty(Q))
FatalError("Empty queue");
X = Q->Array[Q->Front];
Q->Front++;
if(Q->Front == Q->Capacity)
Q->Front = 0;
return X;
}
queuemain.c队列测试
#include <stdio.h>
#include "queue.h"
int main(void)
{
Queue Q;
int i;
Q = CreateQueue();
for(i = 0; i < 10; i++)
Enqueue(i, Q);
while(!IsEmpty(Q) && i < 15)
{
printf("%d ", Head(Q));
Dequeue(Q);
++i;
}
putchar('\n');
for(; i< 20; ++i)
Enqueue(i, Q);
while(!IsEmpty(Q))
printf("%d ", Dequeue(Q));
putchar('\n');
DestoryQueue(Q);
Q = CreateQueue();
for(i = 20; i <= 30; i++)
Enqueue(i, Q);
while(!IsEmpty(Q))
printf("%d ", Dequeue(Q));
return 0;
}
测试结果,如下图所示