C语言 链队

#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);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值