P22-c++自己设计一个队列

1. 队列模扒

进一步了解类后,可将这方面的知识用于解决编程问题。
A 银行打算在 B 超市开设一个 自动柜员机(ATM)。
B超市的管理者担心排队等待使用ATM的人流会干扰超市的交通,希望限
制排队等待的人数。
A银行希望对顾客排队等待的时间进行估测。要编写一个程序来模拟这种情况,让超市的管理者可以了解ATM可能造成的影响。

对于这种问题,最自然的方法是使用顾客队列。队列是一种抽象的数据类型( Abstract Data Type,ADT),可以存储有序的项目序列。
新项目被添加在队尾,并可以删除队首的项目。队列有点像栈,但栈在同一端进行添加和删除。
这使得栈是一种后进先出(LIFO,last-in,frst-out)的结构,而队列是先进先出(FIFO, first-in,first-out)的。从概念上说,队列就好比是收款台或ATM前面排的队,所以对于上述问题,队列非常合适。
因此,工程的任务之一是定义一个 Queue类(第16章将介绍标准模板库类 queue,也将介绍如何开发自己的类)
队列中的项目是顾客。 A 银行的代表介绍:通常,三分之一的顾客只需要一分钟便可获得服务,三分之一的顾客需要两分钟,另外三分之一的顾客需要三分钟。另外,顾客到达的时间是随机的,但每小时使用自动柜员机的顾客数量相当稳定。
工程的另外两项任务是:设计一个表示顾客的类:编写一个程序来模拟顾客和队列之间的交互(参见图12.7)。
在这里插入图片描述

1. 队列类

首先需要设计一个 Queue类。这里先列出队列的特征

  • 队列存储有序的项目序列
  • 队列所能容纳的项目数有一定的限制
  • 应当能够创建空队列;
  • 应当能够检查队列是否为空;
  • 应当能够检査队列是否是满的
  • 应当能够在队尾添加项目;
  • 应当能够从队首删除项目;
  • 应当能够确定队列中项目数。
    设计类时,需要开发公有接口和私有实现。
  1. Queue类的接ロ
    从队列的特征可知, Queue类的公有接口应该如下:
/*
	author:梦悦foundation
	公众号:梦悦foundation
	可以在公众号获得源码和详细的图文笔记
*/

class Queue
{
   
	enum {
   Q_SIZE = 10};
private:

public:
	Queue(int qs = Q_SIZE); //创建一个 10个项目的限制的队列
	~Queue();
	bool IsEmpty();
	bool IsFull();
	int QueueCount() const;
	bool EnQueue(const Item & item); //增加一个项目到队列里去
	bool DeQueue(Item & item); //取走一个
}

构造函数创建一个空队列。
默认情况下,队列最多可存储10个项目,但是可以用显式初始化参数覆盖该默认值:

Queue line1; // queue with 10-item limit
Queue line2 (20); // queue with 20-item limit

使用队列时,可以使用 typedef来定义tem(第14章将介绍如何使用类模板)。

2. Queue类的实现

确定接口后,便可以实现它。首先,需要确定如何表示队列数据。
一种方法是使用new动态分配一个数组,它包含所需的元素数。然而,对于队列操作而言,数组并不太合适。例如,删除数组的第一个元素后,需要将余下的所有元素向前移动一位:否则需要作一些更费力的工作,如将数组视为是循环的。然而,链表能够很好地满足队列的要求。链表由节点序列构成。每一个节点中都包含要保存到链表中的信息以及一个指向下一个节点的指针。
对于这里的队列来说,数据部分都是一个Item类型的值,因此可以使用下面的结构来表示节点:

struct Node
{
   
	Item item; // data stored in the node
	struct Node *next; //pointer to next node
}

图12.8说明了链表。
在这里插入图片描述
如图12.8所示是一个单向链表,因为每个节点都只包含一个指向其他节点的指针。
知道第一个节点的地址后,就可以沿指针找到后面的每一个节点。通常,链表最后一个节点中的指针被设置为NUL(或0),以指出后面没有节点了。在C++11中,应使用新增的关键字 nullptr。要跟踪链表,必须知道第一个节点的地址。
可以让 Queue类的一个数据成员指向链表的起始位置。
具体地说,这是所需要的全部信息,有了这种信息后,就可以沿节点链找到任何节点。然而,由于队列总是将新项目添加到队尾,因此包含一个指向
最后一个节点的数据成员将非常方便(参见图12.9)。
在这里插入图片描述
此外,还可以使用数据成员来跟踪队列可存储的最大项目数以及当前的项目数。所以,类声明的私有部分与下面类似:

class Queue {
   
private:
	struct Node {
   
		Item item;
		struct Node *next;
	};
	Node *front; //最开头的项目
	Node *rear;	//最末尾的项目
	int items;	//队列当中项目的数量
	const int qsize;
};

上述声明使用了C+的一项特性:在类中嵌套结构或类声明。
通过将Node声明放在 Queue类中,可以使其作用域为整个类。
也就是说,Node是这样一种类型:可以使用它来声明类成员,也可以将它作为类方法中的类型名称,但只能在类中使用。
这样,就不必担心该Node声明与某些全局声明或其他类中声明的Node发生冲突。
有些较老的编译器不支持嵌套的结构和类,如果您的编译器是这样的,则必须将Node结构定义为全局的,将其作用域设置为整个文件。

1. 嵌套结构和类

在美声明中声明的结构、类或枚举被称为是被嵌套在类中,其作用域为整个类。
这种声明不会创建数据对象,而只是指定了可以在类中使用的类型。
如果声明是在类的私有部分进行的,则只能在这个类使用被声明的类型;如果声明是在公有部分进行的,则可以从类的外部通过作用域解析运算符使用被声明的类型。
例如,如果Node是在 Queue类的公有部分声明的,则可以在类的外面声明 Queue::Node美型的变量。

设计好数据的表示方式后,接下来需要编写类方法

3.类方法

类构造函数应提供类成员的值。由于在这个例子中,队列最初是空的,因此队首和队尾指针都设置为NULL(0或 nullpt),并将 items设置为0。另外,还应将队列的最大长度 size设置为构造函数参数qs的值。下面的实现方法无法正常运行:

Queue: Queue(int qs)
{
   
	front = rear =  NULL;
	items = 0;
	qs1ze qs; // not acceptable!
}

问题在于 size是常量,所以可以对它进行初始化,但不能给它赋值。
从概念上说,调用构造函数时,对象将在括号中的代码执行之前被创建。因此,调用 Queue( int qs)构造函数将导致程序首先给4个成员变量分配内存。然后,程序流程进入到括号中,使用常规的赋值方式将值存储到内存中。

因此,对于 const数据成员,必须在执行到构造函数体之前,即创建对象时进行初始化。
C++提供了一种特殊的语法来完成上述工作,它叫做成员初始化列表( member initializer list)。成员初始化列表由逗号分隔的初始化列表组成(前面带冒号)。

它位于参数列表的右括号之后、函数体左括号之前。如果数据成员的名称为 mdata,并需要将它初始化为val,则初始化器为 mdata(val)。使用这种表示法,可以这样编写 Queue的构造函数:

Queue::Queu
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值