C Primer Plus学习 六十二 队列 ADT(二)

实现接口函数

现在我们开始编写接口的实现代码。首先,把队列初始化为空意味着设置首尾指针为NULL并设置项 数(items成员)为0:

void InitializeQueue (Queue * pq)

{

pq->front = pq->rear = NULL:

 pq->items = 0;

}

然后,items成员使得对满列和空列的检查以及返回队列中的项数变得简单:

bool QueuelsFull (const Queue * pq)

(

return pq->icems == MAXQUEUE:

}

bool QueuelsEmpty (const Queue * pq)

{

return pq->items == 0;

}

int QueueltemCount (const Queue * pq)

{

return pq->items;

}

向队列中添加项目包括下列步骤:

1. 创建新节点。

2. 把项目复制到新节点。

3. 设置节点的next指针为NULL,表明该节点是列表中的最后一个节点。

4.设置当前尾节点的next指针指向新节点,从而将新节点链接到队列中。

5. 把rear指针设置为指向新节点,以便找到最后的节点。

6. 项目个数加1。

       函数还需要处理两种特殊情况。首先,如果队列为空,front指针也应该设为指向新节点。因为如果只 有一个节点,那么这个节点既是队首也是队尾„第二,如果函数不能给节点获取所需的内存,就需要执行 -些动作。因为我们假设使用小型队列,这样的情况应该很少见,所以如果程序运行的内存不足,我们只 是让函数中止程序。EnQueue ()的代码如下:

bool EnQueue (Item item. Queue * pq)

{

Node * pnew; if (QueuelsFull (pq)) return false;

pnew = (Node *) malloc (sizeof (Node));

 i f (pnew == NULL)

{

fprintf (stderr. •Unable to allocate memory.'\n"); exit (1 );

}

CopyToNode (item, pnew): pnew->next = NULL; if (QueuelsEmpty (pq))

pq->front = pnew; /*项⑴立于队列首端 */

else

pq->rear~>next= pnew; /* 链接到队列尾端 V

pq->rear = pnew: /* id录队列尾端的位置 V

pq->items++; /*队列项目个数增1 */

return true;

}

CopyToNode ()函数是把项目复制到节点中的静态函数:

static void CopyToNode (Item item. Node * pn)

pn->item = item;

}

从队列首端删除项目包括下列步骤:

1. 把项目复制到一个给定的变量中。

2. 释放空闲节点使用的内存。

3. 重置首指针,使其指向队列中的下一项。

4. 如果最后一项被删除,把首尾指针均重置为NULL。

5. 项目数减1。

下面是完成这些步骤的代码:

bool DeQueue (Item * pitem, Queue * pq)

{

Node * pts

if (QueueIsEmpty (pq)) return false;

CopyToItem (pq->front,pitem):

 pt = pq->front: 

pq->front = pq->front->next;

 free (pt); pq->itens--;

 if (pq->items == 0) 

pq->rear = NULL:

return true;

}

       关于指针有些事项必须注意。第一,在删除最后一项时,代码没有明确设置front指针为NULL。因为它已 经把tom指针设置为被删除节点的next指针。如果这个节点是最后的节点,其next指针就为NULL,所以front 指针就被设置为NULL。第二,代码使用临时指针pt来保存被删除节点的位置。因为指向第一个节点的正式指 针(pq->next)被重置为指向下一个节点,所以如果没有临时指针,程序将不知道该释放哪个内存块。

我们可以使用DeQueue ()函数清空一个队列。循环调用DeQueue ()直到队列为空:

void EmptyTheQueue (Queue * pq)

{

Item duirany:

while (!QueueIsEmpty (pq)) 

DeQueue (&dummy, pq);

保持ADT的完整

       当您定义了一个ADT的接口之后,您只能使用接口函数来处理数据类型。比如,注意 DeQueue ()依赖EnQueue ()来正确设置指针并设置末节点的next指针为NULL,,如果在一 个使用该ADT的程序中,您直接操作队列的某些部分,将有可能破坏接口包中函数之间的协作 关系。

/* queue.c --队列类型的实现文件*/

#include<stdio.h>

#include<stdlib.h>

#include"queue.h"


/*局部函数*/

static void CopyToNode(Item item0,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 EnAddQueue(Item item,Queue *pq)

{

Node *pnew;

if(QueueIsFull(pq))

     return false;

    pnew=(Node *)malloc(sizeof(Node));

    if(pnew==NULL)

    {

    fprintf(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++;/*队列项目个数增1 */

    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 item0,Node *pn)

{

pn->item=item0;

}



static void CopyToItem(Node *pn,Item *pi)

{

*pi=pn->item;

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值