queue.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // Copyright 2006 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Datastructure: Queue.
  16. *
  17. *
  18. * This file provides the implementation of a FIFO Queue structure.
  19. * API is similar to that of com.google.common.collect.IntQueue
  20. *
  21. * The implementation is a classic 2-stack queue.
  22. * There's a "front" stack and a "back" stack.
  23. * Items are pushed onto "back" and popped from "front".
  24. * When "front" is empty, we replace "front" with reverse(back).
  25. *
  26. * Example:
  27. * front back op
  28. * [] [] enqueue 1
  29. * [] [1] enqueue 2
  30. * [] [1,2] enqueue 3
  31. * [] [1,2,3] dequeue -> ...
  32. * [3,2,1] [] ... -> 1
  33. * [3,2] [] enqueue 4
  34. * [3,2] [4] dequeue -> 2
  35. * [3] [4]
  36. *
  37. * Front and back are simple javascript arrays. We rely on
  38. * Array.push and Array.pop being O(1) amortized.
  39. *
  40. * Note: In V8, queues, up to a certain size, can be implemented
  41. * just fine using Array.push and Array.shift, but other JavaScript
  42. * engines do not have the optimization of Array.shift.
  43. *
  44. */
  45. goog.provide('goog.structs.Queue');
  46. goog.require('goog.array');
  47. /**
  48. * Class for FIFO Queue data structure.
  49. *
  50. * @constructor
  51. * @template T
  52. */
  53. goog.structs.Queue = function() {
  54. /**
  55. * @private {!Array<T>} Front stack. Items are pop()'ed from here.
  56. */
  57. this.front_ = [];
  58. /**
  59. * @private {!Array<T>} Back stack. Items are push()'ed here.
  60. */
  61. this.back_ = [];
  62. };
  63. /**
  64. * Flips the back stack onto the front stack if front is empty,
  65. * to prepare for peek() or dequeue().
  66. *
  67. * @private
  68. */
  69. goog.structs.Queue.prototype.maybeFlip_ = function() {
  70. if (goog.array.isEmpty(this.front_)) {
  71. this.front_ = this.back_;
  72. this.front_.reverse();
  73. this.back_ = [];
  74. }
  75. };
  76. /**
  77. * Puts the specified element on this queue.
  78. * @param {T} element The element to be added to the queue.
  79. */
  80. goog.structs.Queue.prototype.enqueue = function(element) {
  81. this.back_.push(element);
  82. };
  83. /**
  84. * Retrieves and removes the head of this queue.
  85. * @return {T} The element at the head of this queue. Returns undefined if the
  86. * queue is empty.
  87. */
  88. goog.structs.Queue.prototype.dequeue = function() {
  89. this.maybeFlip_();
  90. return this.front_.pop();
  91. };
  92. /**
  93. * Retrieves but does not remove the head of this queue.
  94. * @return {T} The element at the head of this queue. Returns undefined if the
  95. * queue is empty.
  96. */
  97. goog.structs.Queue.prototype.peek = function() {
  98. this.maybeFlip_();
  99. return goog.array.peek(this.front_);
  100. };
  101. /**
  102. * Returns the number of elements in this queue.
  103. * @return {number} The number of elements in this queue.
  104. */
  105. goog.structs.Queue.prototype.getCount = function() {
  106. return this.front_.length + this.back_.length;
  107. };
  108. /**
  109. * Returns true if this queue contains no elements.
  110. * @return {boolean} true if this queue contains no elements.
  111. */
  112. goog.structs.Queue.prototype.isEmpty = function() {
  113. return goog.array.isEmpty(this.front_) && goog.array.isEmpty(this.back_);
  114. };
  115. /**
  116. * Removes all elements from the queue.
  117. */
  118. goog.structs.Queue.prototype.clear = function() {
  119. this.front_ = [];
  120. this.back_ = [];
  121. };
  122. /**
  123. * Returns true if the given value is in the queue.
  124. * @param {T} obj The value to look for.
  125. * @return {boolean} Whether the object is in the queue.
  126. */
  127. goog.structs.Queue.prototype.contains = function(obj) {
  128. return goog.array.contains(this.front_, obj) ||
  129. goog.array.contains(this.back_, obj);
  130. };
  131. /**
  132. * Removes the first occurrence of a particular value from the queue.
  133. * @param {T} obj Object to remove.
  134. * @return {boolean} True if an element was removed.
  135. */
  136. goog.structs.Queue.prototype.remove = function(obj) {
  137. return goog.array.removeLast(this.front_, obj) ||
  138. goog.array.remove(this.back_, obj);
  139. };
  140. /**
  141. * Returns all the values in the queue.
  142. * @return {!Array<T>} An array of the values in the queue.
  143. */
  144. goog.structs.Queue.prototype.getValues = function() {
  145. var res = [];
  146. // Add the front array in reverse, then the back array.
  147. for (var i = this.front_.length - 1; i >= 0; --i) {
  148. res.push(this.front_[i]);
  149. }
  150. var len = this.back_.length;
  151. for (var i = 0; i < len; ++i) {
  152. res.push(this.back_[i]);
  153. }
  154. return res;
  155. };