像栈一样,队列(queue)也是表。然而,使用队列时插入是在一端进行的,而删除则是在另一端进行的。
队列的基本操作是 enqueue(入队),它是在表的末端(称为队尾)插入一个元素;dequeue(出队),它是删除(并返回)表的开头(叫作队头)的元素。
对于每一个队列数据结构,我们保留一个数组 theRay以及位置 front和back,它们代表队列的两端。我们还要记录实际存在于队列中的元素的个数 currentsize。
操作应该是清楚的。要 enqueue元素x,可将 currentsize和back增1,然后置theArray[back]=x。要 dequeue一个元素,可以置返回值为 theArray[Front],将 currentsize减1,再将front增1。其他的方法也可以使用(将在后面讨论)。现在论述错误的检测。
这种实现存在一个潜在的问题。经过10次 enqueue后,队列似乎是满了,因为back现在是数组的最后一个下标,而下一次执行 enqueue就会是个不存在的位置。然而,队列中也许只存在几个元素,因为若干元素可能已经出队了。像栈一样,即使在有许多操作的情况下队列也常常不是很大。
简单的解决方法是,只要fron或back到达数组的尾端,就绕回到开头。下列图显示了在某些操作期间的队列情况。这称为循环数组(circular array)实现
实现回绕所需要的附加代码是极小的(虽然它可能使得运行时间加倍)。如果 front或back增1使得它超越了数组,那么其值就要重置为数组的第一个位置。
3.7.3队列的应用
事实上每一个实际生活中的排队都(应该)是一个队列。例如,在售票口排列的队是队列,因为服务的顺序是先到的先买票
另一个例子是关于计算机网络的。有许多种PC机的网络设置,其中磁盘是放在台叫作文件服务器(file server)的机器上的。使用其他计算机的用户是按照先到先使用的原则访问文件的,因此其数据结构是一个队列
正如栈一样,队列还有其他丰富的用途
小结
本章描述了一些ADT的概念,并且利用三种最常见的抽象数据类型闻述了这个概念。主要目的就是将抽象数据类型的具体实现与它们的功能分开。程序必须知道操作都做些什么,但是如果不知道如何去做就更好
在所有的计算机科学中,表、栈和队列或许都是三个基本的数据结构,大量的例子证明了它们广泛的用途。特别地,我们看到栈是如何用来记录函数调用以及是如何真实地实现递归的。这对于理解是非常重要的,其原因不只是它使得过程语言成为可能,而且还因为知道递归的实现而揭开了围绕其使用的神秘面纱。虽然递归非常强大,但是它并不是完全随意的操作;递归的误用和乱用可能导致程序崩溃。