一般队列接口(ADT)

        设想你在超市排队付款,你将从队尾进入,从队头离开--这便是一个队列。

        在《C Primer Plus》一书中,队列的定义是“一种’先进先出‘(first in first out,即FIFO)的数据形式”。队列(queue)实际上是具有两个特殊属性的链表。1.新项只能从队列的末尾添加;2只能从链表的开头移除项。

        明白了这些后,我们实际上就可以把队列想象成一个环来帮助理解,我们将需要一个正常的链表Node结构体,同时需要额外一个Queue的结构体,里面存放指向队列的头指针和尾指针。

         我们还需要什么呢?哦对了,一个队伍它所容纳的人数有限,这样才可控。类比一下队列,我们的队列需要一个最大容限。我们一般做的队列是一个小型的,这样方便我们动态分配内存(当然大型的并不是没有,这里我们不展开讨论)。那么我们又该如何判断队列是否已满呢?常规的方法是有两个:1.利用tail和head的差值进行计算;2.在Queue结构体中,放入int items来记录项数,在每次的添加Node的同时,让items自增,并在下次添加前与最大容量比较。

        这里我们仍然选择着重讨论第二种,下面我们来看一下代码的实现。(摘自《C Primer Plus》)

queue.h文件:

#ifndef _QUEUE_H_
#define _QUEUE_H_
#include <stdbool.h>

//在这里插入Item类型的定义
typedef int Item;
// typedef struct item
// {
//     int gumption;
//     int charisma;
// }item;

#define MAXQUEUE 10

typedef struct node
{
    Item item;
    struct node * next;
}Node;

typedef struct queue
{
    Node * front;//指向队列首项的指针
    Node * rear;//指向队列尾项的指针
    int items;//队列中的项数
}Queue;

//操作:初始化队列
//前提条件:pq指向一个队列
//后置条件:队列被初始化为空
void InitializeQueue(Queue * pq);

//操作:检查队列是否已满
//前提条件:pq指向之前被初始化的队列
//后置条件:如果队列已满则返回true,否则返回false
bool QueueIsFull(const Queue * pq);

//操作:检查队列是否为空
//前置条件:pq指向之前被初始化的队列
//后置条件:如果队列为空则返回true,否则返回false
bool QueueIsEmpty(const Queue *pq);

//操作:确定队列中的项数
//前提条件:pq指向之前被初始化的队列
//后置条件:返回队列中的项数
int QueueItemCount(const Queue * pq);

//操作:在队列末尾添加项
//前置条件:pq指向之前被初始化的队列;item是要被添加在队列末尾的项
//后置条件:如果队列不为空,item将被添加在队列的末尾,该函数返回true;否则,队列不改变,该函数返回false
bool EnQueue(Item item,Queue *pq);

//操作:从队列的开头删除项
//前提条件:pq指向之前被初始化的队列
//后置条件:如果队列不为空,队列首端的item将被拷贝到*pitem中并被删除,且函数返回true;
//          如果该操作使得队列为空,则重置队列为空
//          如果队列在操作前为空,该函数返回false
bool DeQueue (Item *pitem, Queue *pq);

//操作:清空队列
//前提条件:pq指向之前被初始化的队列
//后置条件:队列被清空
void EmptyTheQueue(Queue * pq);

#endif

queue.c文件:

#include <stdio.h>
#include <stdlib.h>
#include "queue.h"

//局部函数
static void CopyToNode(Item item, Node * pn);
static void CopyToItem(Node *pn,Item *pi);

void InitializeQueue(Queue *pq)
{
    pq->front = pq->rear = NULL;
    pq->items = 0;
}

bool QueueIsFull(const Queue *pq)
{
    return pq->items == MAXQUEUE;
}

bool QueueIsEmpty(const Queue *pq)
{
    return pq->items == 0;
}

int QueueItemCount(const Queue *pq)
{
    return pq->items;
}

bool EnQueue(Item item,Queue *pq)
{
    Node *pnew;

    if(QueueIsFull(pq))
        return false;
    pnew = (Node *)malloc(sizeof(Node));
    if(pnew == NULL)
    {
        fprint(stderr,"Unable to allocate memory!\n");
        exit(1);
    }
    CopyToNode(item,pnew);
    pnew->next=NULL;
    if(QueueIsEmpty(pq))
        pq->front = pnew;//项位于队列的顶端
    else
        pq->rear->next=pnew;//链接到队列的尾端
    pq->rear = pnew;//记录队列尾端的位置
    pq->items++;

    return true;
}

bool DeQueue(Item *pitem, Queue *pq)
{
    Node *pt;

    if(QueueIsEmpty(pq))
        return false;
    CopyToItem(pq->front, pitem);
    pt = pq->front;
    pq->front = pq->front->next;
    free(pt);
    pq->items--;
    if(pq->items == 0)
        pq->rear = NULL;

    return true;
}

//清空队列
void EmptyTheQueue(Queue *pq)
{
    Item dummy;
    while (!QueueIsEmpty(pq))
        DeQueue(&dummy,pq);
}

//局部函数
static void CopyToNode(Item item,Node *pn)
{
    pn->item = item;
}

static void CopyToItem(Node *pn, Item *pi)
{
    *pi = pn->item;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北城南笙(在校学习)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值