队列先进先出,涉及到两个位置的操作,一个是队首,一个是队尾,我们分别用两个整型变量来表示队首和队尾,另外需要注意的是我们实现队列时要借助循环数组,具体在代码中已经很清楚了。实现过程中的技巧与用数组实现栈时大多数一样。
首先,我们来声明类型,结构和例程。
/**
* @file Queue.h
* @brief 用链表实现队列-声明ADT部分
* @details
* @author jason.mrbourne@gmail.com
* @date 2014-5-20
*/
#include <stdio.h>
#ifndef _Queue_h
//实现队列所需的结构和类型
typedef int ElementType;
struct QueueRecord;
typedef struct QueueRecord *Queue;
int IsEmpty(Queue Q); //判空
int IsFull(Queue Q); //判满
Queue CreateQueue(int MaxElements); //创建队列
void DisposeQueue(Queue Q); //消除队列
void MakeEmpty(Queue Q); //置空队列
void Enqueue(ElementType X, Queue Q); //入队
ElementType Front(Queue Q); //返回队首
void Dequeue(Queue Q); //出队
ElementType FrontAndDequeue(Queue Q); //出队并返回队首
void FatalError(char *str); //错误信息
static int Succ(int Value, Queue Q); //队首或队尾的前移
#endif // _Queue_h
然后实现他们:
/**
* @file Queue.c
* @brief 用链表实现队列-实现部分
* @details
* @author jason.mrbourne@gmail.com
* @date 2014-5-20
*/
#include <stdlib.h>
#include <Queue.h>
#define MinQueueSize (5) //最小队列大小
struct QueueRecord
{
int Front; //队首
int Rear; //队尾
int Size; //大小
int Capacity; //容量
ElementType *Array; //队列数组
};
//判断队列是否为空
int IsEmpty(Queue Q)
{
return Q->Size == 0;
}
//构造空队列
void MakeEmpty(Queue Q)
{
Q->Size = 0;
Q->Front = 1; //初始化队列中队首比队尾大1
Q->Rear = 0;
}
//错误信息
void FatalError(char *str)
{
printf("%s", str);
}
//队头或队尾的移动
static int Succ(int Value, Queue Q)
{
if (++Value == Q->Capacity) //这里用来实现一个循环队列
Value = 0;
return Value;
}
//入队
void Enqueue(ElementType X, Queue Q)
{
if (Q->Size == Q->Capacity)
FatalError("FUll Queue.");
else
{
++Q->Size; //大小加1
Q->Rear = Succ(Q->Rear, Q); //队尾前移
Q->Array[Q->Rear] = X; //队尾加入元素
}
}
//判断队列是否满
int IsFull(Queue Q)
{
return Q->Size == Q->Capacity;
}
//创建队列
Queue CreateQueue(int MaxElements)
{
Queue Q;
if (MaxElements < MinQueueSize)
FatalError("Queue Size is too small.");
Q = malloc(sizeof(struct QueueRecord));
if (Q == NULL)
FatalError("Out of space");
Q->Array = malloc(sizeof(ElementType)*MaxElements);
if (Q->Array == NULL)
FatalError("Out of space.");
Q->Capacity = MaxElements;
MakeEmpty(Q);
return Q;
}
//消除队列
void DisposeQueue(Queue Q)
{
if (Q != NULL)
{
free(Q->Array);
free(Q);
}
}
//返回队首元素
ElementType Front(Queue Q)
{
if(IsEmpty(Q))
FatalError("Empty Queue");
else
return Q->Array[Q->Front];
return 0;
}
//出队
void Dequeue(Queue Q)
{
if (IsEmpty(Q))
FatalError("Empty Queue.");
else
{
Q->Front = Succ(Q->Front, Q);
Q->Size--;
}
}
//出队并返回队首
ElementType FrontAndDequeue(Queue Q)
{
ElementType TmpCell;
if (IsEmpty(Q))
FatalError("Empty Queue");
else
{
Q->Size--;
TmpCell = Q->Array[Q->Front];
Q->Front = Succ(Q->Front,Q);
return TmpCell;
}
return 0;
}
最后在主程序中测试。
/**
* @file main.c
* @brief 用链表实现队列-测试部分
* @details
* @author jason.mrbourne@gmail.com
* @date 2014-5-20
*/
#include <stdio.h>
#include <stdlib.h>
#include <Queue.h>
int main()
{
//入队3个并依次出队
Queue Q = CreateQueue(100);
Enqueue(1,Q);
Enqueue(2,Q);
Enqueue(3,Q);
while (!IsEmpty(Q))
printf("%d\t", FrontAndDequeue(Q));
}
经过了这几个程序,我们大体上已经掌握了链表,队列和栈的基本实现和常用例程,当然,这只是个基础,对于这几个程序,一个合格的程序员应该做到烂熟于心,关于这几个数据结构的常用应用,我会在后面慢慢来做,下一步,我们就开始学习数据结构中另一个非常重要的部分—排序。