C Primer Plus学习 六十二 队列 ADT(二)
2016-10-21 10:36
281 查看
实现接口函数
现在我们开始编写接口的实现代码。首先,把队列初始化为空意味着设置首尾指针为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指针也应该设为指向新节点。因为如果只 有一个节点,那么这个
eb2f
节点既是队首也是队尾„第二,如果函数不能给节点获取所需的内存,就需要执行 -些动作。因为我们假设使用小型队列,这样的情况应该很少见,所以如果程序运行的内存不足,我们只 是让函数中止程序。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;
}
现在我们开始编写接口的实现代码。首先,把队列初始化为空意味着设置首尾指针为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指针也应该设为指向新节点。因为如果只 有一个节点,那么这个
eb2f
节点既是队首也是队尾„第二,如果函数不能给节点获取所需的内存,就需要执行 -些动作。因为我们假设使用小型队列,这样的情况应该很少见,所以如果程序运行的内存不足,我们只 是让函数中止程序。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;
}
相关文章推荐
- C Primer Plus学习 六十一 队列 ADT(一)
- C Primer Plus学习 六十三 队列 ADT(三)
- C++ Primer Plus学习:第四章 复合类型(4)
- C Primer Plus学习计划
- [学习笔记][C++Primer Plus]使用cout格式化输出字符串
- C++ Primer Plus学习:第三章 处理数据(2)
- C++ Primer Plus学习:第四章 复合类型(1)
- C++ primer plus学习:第一章 预备知识
- C++ Primer Plus学习:第七章 函数-C++的编程模块(3)
- C++ Primer Plus学习:第四章 复合类型(6)
- C++ Primer Plus学习:第五章 循环和关系表达式(1)
- C++ Primer Plus学习:第八章 函数探幽(1)
- C++ Primer Plus 第二章 开始学习C++
- C++ Primer Plus学习:第六章 分支语句和逻辑操作符(2)
- C++ Primer Plus学习:第七章 函数-C++的编程模块(1)
- [学习笔记][C++Primer Plus]String类的使用
- 学习C++ Primer Plus 存储作用域、链接性、连续性总结
- 学习C++Primer Plus 函数探幽总结
- C++ Primer Plus学习:第三章 处理数据(1)
- C++ Primer Plus学习:第四章 复合类型(2)