一、单链队列的链式存储结构
相关代码下载链接:http://download.csdn.net/detail/shengshengwang/8141633
队列是操作受限的线性表,只允许在队尾插入元素,在队头删除元素。对于链队列结构,为了便于插入元素,设立了队尾指针,这样插入元素的操作便与队列长度无关。存储结构,如下所示:
typedef int QElemType;
typedef struct QNode
{
QElemType data;
QNode *next;
} *QueuePtr;
struct LinkQueue
{
QueuePtr front, rear; // 队头、队尾指针
};
二、单链队列的链式存储结构的基本操作
(1)构建队列
void InitQueue(LinkQueue &Q)
{ // 构造一个空队列Q
Q.front = Q.rear = (QueuePtr)malloc(sizeof(QNode)); // 生成头结点
if(!Q.front) // 生成头结点失败
exit(3);
Q.front->next = NULL; // 头结点的next域为空
}
(2)销毁队列
void DestroyQueue(LinkQueue &Q)
{ // 销毁队列Q(无论空否均可)
while(Q.front) // Q.front不为空
{
Q.rear = Q.front->next; // Q.rear指向Q.front的下一个结点
free(Q.front); // 释放Q.front所指结点
Q.front = Q.rear; // Q.front指向Q.front的下一个结点
}
}
(3)队列判空
int QueueEmpty(LinkQueue Q)
{ // 若队列Q为空队列,则返回TRUE;否则返回FALSE
if(Q.front->next == NULL)
return 1;
else
return 0;
}
(4)插入队列
void EnQueue(LinkQueue &Q, QElemType e)
{ // 插入元素e为队列Q的新的队尾元素
QueuePtr p;
p = (QueuePtr)malloc(sizeof(QNode)); // 动态生成新结点
if(!p)
exit(3); // 若分配堆内存失败,则退出
p->data = e; // 将值e赋给新结点
p->next = NULL; // 新结点的指针域为空
Q.rear->next = p; // 原队尾结点的指针指向新结点
Q.rear = p; // 尾指针指向新结点
}
(5)删除队列
int DeQueue(LinkQueue &Q, QElemType &e)
{ // 若队列Q不空,删除Q的队头元素,用e返回其值
// 并返回OK;否则返回ERROR
QueuePtr p;
if(Q.front == Q.rear) // 队列空
return 0;
p = Q.front->next; // p指向队头结点
e = p->data; // 将队头元素的值赋给e
Q.front->next = p->next; // 头结点指向下一个结点
if(Q.rear == p) // 删除的是队尾结点
Q.rear = Q.front; // 修改队尾指针指向头结点(空队列)
free(p); // 释放队头结点
return 1;
}
(6)取得队列首元素
int GetHead(LinkQueue Q, QElemType &e)
{ // 若队列Q不空,则用e返回Q的队头元素,并返回OK;否则返回ERROR
QueuePtr p;
if(Q.front == Q.rear) // 队列空
return 0;
p = Q.front->next; // p指向队头结点
e = p->data; // 将队头元素的值赋给e
return 1;
}
(7)遍历队列
void print(QElemType e)
{
printf("%d ", e);
}
void QueueTraverse(LinkQueue Q, void(*visit)(QElemType))
{ // 从队头到队尾依次对队列Q中的每个元素调用visit()
QueuePtr p = Q.front->next; // p指向队头结点
while(p) // p指向结点
{
visit(p->data); // 对p所指元素调用visit()
p = p->next;
}
printf("\n");
}
三、检验基本操作的主函数
void main()
{
QElemType d;
LinkQueue q;
InitQueue(q); // 构造空队列q,失败则退出
// 依次入队3个元素
EnQueue(q, -5);
EnQueue(q, 5);
EnQueue(q, 10);
printf("队列的元素依次为:");
QueueTraverse(q, print);
GetHead(q, d);
DeQueue(q, d);
printf("队列的元素依次为:");
QueueTraverse(q, print);
}
四、队列抽象数据类型定义
ADT Queue{
数据对象:D={ai|ai∈ElemSet, i=1,2, …,n, n≥0}
数据关系:R1={<ai-1,ai>|ai-1,ai∈D, i=1,2, …,n }
约定a1为队列头,an为队列尾。
基本操作:
InitQueue( &Q )
操作结果:构造一个空队列Q。
DestroyQueue ( &Q )
初始条件:队列Q已存在。
操作结果:销毁队列Q。
ClearQueue ( &Q )
初始条件:队列Q已存在。
操作结果:将Q清为空队列。
QueueEmpty( Q )
初始条件:队列Q已存在。
操作结果:若Q为空队列,则返回TRUE,否则返回FALSE。
QueueLength( Q )
初始条件:队列Q已存在。
操作结果:返回Q的数据元素个数,即队列的长度。
GetHead( Q, &e )
初始条件:队列Q已存在且非空。
操作结果:用e返回Q的队头元素。
EnQueue( &Q, e )
初始条件:队列Q已存在。
操作结果:插入元素e为Q的新的队尾元素。
DeQueue( &Q, &e )
初始条件:队列Q已存在且非空。
操作结果:删除Q的队头元素,并用e返回其值。
QueueTraverse( Q, visit() )
初始条件:队列Q已存在且非空。
操作结果:从队头到队尾依次对Q的每个数据元素调用函数visit()。一旦visit()失败,则操作失败。
}ADT Queue原文地址:http://blog.csdn.net/ssw_1990/article/details/40980583