#ifndef _LINKQUEUE_H_
#define _LINKQUEUE_H_
#define TRUE 1
#define FALSE 0
/*------------------------------------------------------------
// 链式队列结构的定义
------------------------------------------------------------*/
typedef int ElemType;
typedef struct Node
{
ElemType data; // 元素数据
struct Node *next; // 链式队列中结点元素的指针
} QNode, *QueuePtr;
typedef struct
{
QueuePtr front; // 队列头指针
QueuePtr rear; // 队列尾指针
} LinkQueue;//只包含两个指针,无实际节点内容
/*------------------------------------------------------------
// 链式队列的基本操作
------------------------------------------------------------*/
int InitLinkQueue(LinkQueue *Q);
void DestroyLinkQueue(LinkQueue *Q);
int LinkQueueEmpty(LinkQueue Q);
int LinkQueueLength(LinkQueue Q);
int GetLinkHead(LinkQueue Q, ElemType *e);
void LinkQueueTraverse(LinkQueue Q, void (*fp)(ElemType));
void ClearLinkQueue(LinkQueue *Q);
int PushLinkQueue(LinkQueue *Q, ElemType *e);
int PopLinkQueue(LinkQueue *Q, ElemType *e);
int PrintLinkQueue(LinkQueue *Q);
#endif
/*------------------------------------------------------------
链队算法:先初始化一个节点,并把下一个节点指针设为NULL
入队列,把新建节点的指针,传入上一个节点(尾结点)指针next,并更新(尾结点指针)
出队列,获取头结点数据,把头结点指针向后移,并释放出队列节点
链队的好处:消耗资源随情况而定,对资源大小相对不受限制
链队的坏处:频繁申请释放资源,容易出现内存泄漏
------------------------------------------------------------*/
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <assert.h>
#include "linkqueue.h"
/*------------------------------------------------------------
操作目的: 初始化队列
初始条件: 无
操作结果: 构造一个空的队列
函数参数:
LinkQueue *Q 待初始化的队列
返回值:
bool 操作是否成功
------------------------------------------------------------*/
int InitLinkQueue(LinkQueue *Q)
{
//分配一个头结点节点,头结点尾节点指针均指向它
Q ->front = Q ->rear = (QueuePtr)malloc(sizeof(QNode));
if(Q ->front == NULL){
printf("InitQueue error :malloc fail\n");
return FALSE;
}
Q ->front ->next = NULL;//并将头结点的下一个节点置为NULL
return TRUE;
}
/*------------------------------------------------------------
操作目的: 销毁队列
初始条件: 队列Q已存在
操作结果: 销毁队列Q
函数参数:
LinkQueue *Q 待销毁的队列
返回值:
无
------------------------------------------------------------*/
void DestroyLinkQueue(LinkQueue *Q)
{
assert(Q != NULL);//该函数出错返回
while(Q ->front)
{
Q ->rear = Q ->front ->next;
free(Q ->front);
Q ->front = Q ->rear;
}
}
/*------------------------------------------------------------
操作目的: 判断队列是否为空
初始条件: 队列Q已存在
操作结果: 若Q为空队列,则返回true,否则返回false
函数参数:
LinkQueue Q 待判断的队列
返回值:
bool 是否为空
------------------------------------------------------------*/
int LinkQueueEmpty(LinkQueue Q)
{
assert(Q.front != NULL && Q.rear != NULL);
if(Q.front == Q.rear)
return TRUE;
else
return FALSE;
}
/*------------------------------------------------------------
操作目的: 得到队列的长度
初始条件: 队列Q已存在
操作结果: 返回Q中数据元素的个数
函数参数:
LinkQueue Q 队列Q
返回值:
int 数据元素的个数
------------------------------------------------------------*/
int LinkQueueLength(LinkQueue Q)
{
assert(Q.front != NULL);
QueuePtr p = Q.front;
int Length = 0;
while (p != Q.rear)
{
Length++;
p = p->next;
}
return Length;
}
/*------------------------------------------------------------
操作目的: 得到队列首元素
初始条件: 队列Q已存在
操作结果: 用e返回队列首元素
函数参数:
LinkQueue Q 队列Q
ElemType *e 队列首元素的值
返回值:
bool 操作是否成功
------------------------------------------------------------*/
int GetLinkHead(LinkQueue Q, ElemType *e)
{
assert(Q.front != NULL);
if(LinkQueueEmpty(Q))
return FALSE;
else
{
*e = Q.front ->next ->data;
return TRUE;
}
}
/*------------------------------------------------------------
操作目的: 遍历队列
初始条件: 队列Q已存在
操作结果: 依次对Q的每个元素调用函数fp
函数参数:
LinkQueue Q 队列Q
void (*fp)() 访问每个数据元素的函数指针
返回值:
无
------------------------------------------------------------*/
void LinkQueueTraverse(LinkQueue Q, void (*fp)(ElemType))
{
assert(Q.front != NULL);
QueuePtr p = Q.front ->next;
while(p)
{
(*fp)(p ->data);
p = p ->next;
}
}
/*------------------------------------------------------------
操作目的: 清空队列
初始条件: 队列Q已存在
操作结果: 将队列清空
函数参数:
LinkQueue *Q 队列Q
返回值:
无
------------------------------------------------------------*/
void ClearLinkQueue(LinkQueue *Q)
{
assert(Q ->front != NULL);
QueuePtr p = Q ->front ->next;
while(p)
{
Q ->front ->next = p ->next;
free(p);
p = Q ->front ->next;
}
}
/*------------------------------------------------------------
操作目的: 在队列末尾插入元素e
初始条件: 队列Q已存在
操作结果: 插入元素e作为队列新的尾结点
函数参数:
LinkQueue *Q 队列Q
ElemType e 待插入的数据元素
返回值:
bool 操作是否成功
------------------------------------------------------------*/
int PushLinkQueue(LinkQueue *Q, ElemType *e)
{
QueuePtr temp = (QueuePtr )malloc(sizeof(QNode));
if(!temp)
return FALSE;
temp ->data = *e;
temp ->next = NULL;
Q->rear ->next = temp;
Q ->rear = temp;
return TRUE;
}
/*------------------------------------------------------------
操作目的: 删除链式队列的头结点
初始条件: 队列Q已存在
操作结果: 删除链式队列的头结点
函数参数:
LinkQueue *Q 队列Q
ElemType *e 待插入的数据元素
返回值:
bool 操作是否成功
------------------------------------------------------------*/
int PopLinkQueue(LinkQueue *Q, ElemType *e)
{
if(Q ->front == Q->rear)
return FALSE;
QueuePtr temp = Q->front ->next;
*e = temp ->data;
Q ->front ->next= temp ->next;
if(Q ->rear == temp)
Q ->rear = Q ->front;
free(temp);
return TRUE;
}
/*------------------------------------------------------------
操作目的: 依次从头到尾打印显示队列
初始条件: 队列Q已存在
操作结果:
函数参数:
LinkQueue *Q 队列Q
返回值:
bool 操作是否成功
------------------------------------------------------------*/
int PrintLinkQueue(LinkQueue *Q)
{
if(LinkQueueEmpty(*Q))
return FALSE;
QueuePtr temp = Q->front->next;
printf("PrintLinkQueue:");
while(temp != Q->rear)
{
printf("%d ",temp->data);
temp = temp ->next;
}
printf("%d\n",temp->data);//地址相等,还应打印该节点
}
int main(int argc , char *argv[])
{
int i,k;
ElemType d;
LinkQueue q;
InitLinkQueue(&q);//构造一个空栈
for(i=1;i<=5;i++)
{ PushLinkQueue(&q,&i);
}
PrintLinkQueue(&q);
//QueueTraverse(q,print);
k=LinkQueueEmpty(q);
printf("k=%d\n",k);
k=GetLinkHead(q,&d);
printf("d=%d\n",d);
PopLinkQueue(&q,&d);
k=GetLinkHead(q,&d);
PrintLinkQueue(&q);
printf("d=%d\n",d);
printf("%d\n",LinkQueueLength(q));
ClearLinkQueue(&q);//清空队列
//PrintLinkQueue(&q);
// printf("清空队列后q.front=%u,q.rear=%u,q.front->next=%u\n",q.front,q.rear,q.front->next);
DestroyLinkQueue(&q);
// printf("销毁队列后,q.front=%u,q.rear=%u\n",q.front,q.rear);
}