|
|
51CTO旗下网站
|
|
移动端

3.7.2 队列的数组实现

《数据结构与算法分析:Java语言描述(原书第3版)》第3章表、栈和队列,本章讨论最简单和最基本的三种数据结构。实际上, 每一个有意义的程序都将显式地至少使用一种这样的数据结构, 而栈则在程序中总是要被间接地用到, 不管我们在程序中是否做了声明。本节为大家介绍队列的数组实现。

作者:冯舜玺/陈越 译来源:机械工业出版社|2016-04-13 17:58

3.7.2 队列的数组实现

如同栈的情形一样, 对于队列而言任何的表的实现都是合法的。像栈一样, 对于每一种操作, 链表实现和数组实现都给出快速的O(1)运行时间。队列的链表实现是简单直接的, 我们留作练习。下面讨论队列的数组实现。

对于每一个队列数据结构, 我们保留一个数组theArray以及位置front和back, 它们代表队列的两端。92我们还要记录实际存在于队列中的元素的个数currentSize。下图表示处于某个中间状态的一个队列。

操作应该是清楚的。为使一个元素x入队(即执行enqueue), 我们让currentSize和back增1, 然后置theArray[back]=x。若使元素dequeue(出队), 我们置返回值为theArray[front], 且currentSize减1, 然后使front增1。也可以有其他的方法(将在后面讨论)。现在论述错误检测。

上述实现存在一个潜在的问题。经过10次enqueue后队列似乎是满了, 因为back现在是数组的最后一个下标, 而下一次再enqueue就会是一个不存在的位置。然而, 队列中也许只存在几个元素, 因为若干元素可能已经出队了。像栈一样, 即使在有许多操作的情况下队列也常常不是很大。

简单的解决方法是, 只要front或back到达数组的尾端, 它就又绕回到开头。下面诸图显示在某些操作期间的队列情况。这叫作循环数组(circular array)实现。

实现回绕所需要的附加代码是极小的(不过它可能使得运行时间加倍)。如果front或back增1导致超越了数组, 那么其值就要重置到数组的第一个位置。

有些程序设计员使用不同的方法表示队列的队头和队尾。例如, 有人不使用一项来记录大小, 因为他们依赖于当队列为空(back=front-1)时的基准情形。队列的大小通过比较back和front隐式地算出。这是一种非常隐秘的方法, 因为存在某些特殊的情形, 因此, 如果你想修改用这种方法编写的程序, 那就要特别地小心。如果currentSize不作为明确的数据域被保留, 那么当存在theArray.length-1个元素时队列就满了, 因为只有theArray.length个不同的大小可被区分, 而0是其中的一个。94可以采用任意一种你喜欢的风格, 但要确保你的所有例程都是一致的。由于实现方法有多种选择, 因此如果不使用currentSize域, 那就很可能有必要进行一些注释, 否则会在一个程序中使用两种选择。

在保证enqueue的次数不会大于队列容量的应用中, 使用回绕是没有必要的。像栈一样, 除非主调例程肯定队列非空, 否则dequeue很少执行。因此对这种操作, 只要不是关键的代码, 错误检测常常被跳过。一般说来这并不是无可非议的, 因为这样可能得到的时间节省量是极小的。

喜欢的朋友可以添加我们的微信账号:

51CTO读书频道二维码


51CTO读书频道活动讨论群:342347198

【责任编辑:book TEL:(010)68476606】

回书目   上一节   下一节
点赞 0
分享:
大家都在看
猜你喜欢

读 书 +更多

Linux服务器安全策略详解

Linux主要用于架设网络服务器。如今关于服务器和网站被黑客攻击的报告几乎每天都可以见到,而且随着网络应用的丰富多样,攻击的形式和方法...

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊