PageRenderTime 51ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/Utilities/Collections/Dequeue.cs

#
C# | 930 lines | 573 code | 67 blank | 290 comment | 44 complexity | deae76d0fff26c3a421b9ed577ac069d MD5 | raw file
Possible License(s): Apache-2.0
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using NUnit.Framework;
  5. namespace Delta.Utilities.Collections
  6. {
  7. /// <summary>
  8. /// System.Collections conform class for a ring-queue.
  9. /// </summary>
  10. /// <remarks>
  11. /// The collection support adding and removing at both ends and automatic
  12. /// expansion. The left end of the ring is referred to as head, the right
  13. /// end as tail. Add / Remove needs always the same time, expansion takes
  14. /// more time, depending on the size. Indexed access and enumeration is fast.
  15. /// </remarks>
  16. public class Dequeue<T>
  17. : ICollection<T>, IEnumerable<T>, ICloneable<Dequeue<T>>
  18. {
  19. #region IsReadOnly (Public)
  20. /// <summary>
  21. /// Is read only? Will always return false.
  22. /// </summary>
  23. public bool IsReadOnly
  24. {
  25. get
  26. {
  27. return false;
  28. } // get
  29. }
  30. #endregion
  31. #region AllowsDuplicates (Public)
  32. /// <summary>
  33. /// Allows duplicates? Will always return false.
  34. /// </summary>
  35. public bool AllowsDuplicates
  36. {
  37. get
  38. {
  39. return true;
  40. } // get
  41. }
  42. #endregion
  43. #region IsEmpty (Public)
  44. /// <summary>
  45. /// Is empty? Will return true if we have at least one item.
  46. /// </summary>
  47. public bool IsEmpty
  48. {
  49. get
  50. {
  51. return count != 0;
  52. } // get
  53. }
  54. #endregion
  55. #region Item (Public)
  56. /// <summary>
  57. /// Indexed access to all elements currently in the collection.
  58. /// Indexing starts at 0 (head) and ends at Count-1 (tail).
  59. /// </summary>
  60. /// <returns>Item at this index</returns>
  61. public T this[int index]
  62. {
  63. get
  64. {
  65. if (index < 0 ||
  66. index >= Count)
  67. {
  68. throw new ArgumentOutOfRangeException("index");
  69. }
  70. return innerList[(head + index) % Capacity];
  71. }
  72. set
  73. {
  74. if (index < 0 ||
  75. index >= Count)
  76. {
  77. throw new ArgumentOutOfRangeException("index");
  78. }
  79. innerList[(head + index) % Capacity] = value;
  80. version++;
  81. }
  82. }
  83. #endregion
  84. #region GrowthFactor (Public)
  85. /// <summary>
  86. /// The current factor by which to grow the collection in case of expansion
  87. /// </summary>
  88. /// <typeparam name="T">T</typeparam>
  89. public double GrowthFactor
  90. {
  91. get
  92. {
  93. return growthFactor;
  94. }
  95. set
  96. {
  97. growthFactor = value;
  98. }
  99. }
  100. #endregion
  101. #region Capacity (Public)
  102. /// <summary>
  103. /// The current amount of cells available to the dequeue
  104. /// </summary>
  105. /// <typeparam name="T">T</typeparam>
  106. public int Capacity
  107. {
  108. get
  109. {
  110. return innerList.Length;
  111. }
  112. set
  113. {
  114. if (Capacity >= Count)
  115. {
  116. SetSize(Capacity);
  117. }
  118. else
  119. {
  120. throw new ArgumentException("Capacity was smaller than Count!");
  121. }
  122. }
  123. }
  124. #endregion
  125. #region Version (Public)
  126. /// <summary>
  127. /// The current version of the dequeue. The version is increased with every
  128. /// changing operation. The main use is to invalidate all IEnumerators.
  129. /// </summary>
  130. /// <typeparam name="T">T</typeparam>
  131. public ulong Version
  132. {
  133. get
  134. {
  135. return version;
  136. }
  137. }
  138. #endregion
  139. #region IsSynchronized (Public)
  140. /// <summary>
  141. /// Returns true.
  142. /// </summary>
  143. /// <typeparam name="T">T</typeparam>
  144. public bool IsSynchronized
  145. {
  146. get
  147. {
  148. return true;
  149. }
  150. }
  151. #endregion
  152. #region Count (Public)
  153. /// <summary>
  154. /// The current number of elements in the queue
  155. /// </summary>
  156. /// <typeparam name="T">T</typeparam>
  157. public int Count
  158. {
  159. get
  160. {
  161. return count;
  162. }
  163. }
  164. #endregion
  165. #region SyncRoot (Public)
  166. /// <summary>
  167. /// Returns sync root for this dequeue, which is always this object.
  168. /// </summary>
  169. public object SyncRoot
  170. {
  171. get
  172. {
  173. return this;
  174. }
  175. }
  176. #endregion
  177. #region Protected
  178. #region innerList (Protected)
  179. /// <summary>
  180. /// Inner list for this dequeue
  181. /// </summary>
  182. /// <typeparam name="T">T</typeparam>
  183. protected T[] innerList;
  184. #endregion
  185. #region growthFactor (Protected)
  186. /// <summary>
  187. /// Grow factor
  188. /// </summary>
  189. /// <typeparam name="T">T</typeparam>
  190. protected double growthFactor;
  191. #endregion
  192. #region head (Protected)
  193. /// <summary>
  194. /// Head, tail and count of elements
  195. /// </summary>
  196. /// <typeparam name="T">T</typeparam>
  197. protected int head;
  198. #endregion
  199. #region tail (Protected)
  200. /// <summary>
  201. /// Head, tail and count of elements
  202. /// </summary>
  203. /// <typeparam name="T">T</typeparam>
  204. protected int tail;
  205. #endregion
  206. #region count (Protected)
  207. /// <summary>
  208. /// Head, tail and count of elements
  209. /// </summary>
  210. /// <typeparam name="T">T</typeparam>
  211. protected int count;
  212. #endregion
  213. #region version (Protected)
  214. /// <summary>
  215. /// Version, who needs that?
  216. /// </summary>
  217. /// <typeparam name="T">T</typeparam>
  218. protected ulong version;
  219. #endregion
  220. #endregion
  221. #region Constructors
  222. /// <summary>
  223. /// Create an empty Dequeue with capacity 32 and growth 2
  224. /// </summary>
  225. public Dequeue()
  226. : this(32, 2.0)
  227. {
  228. }
  229. /// <summary>
  230. /// Create an empty Dequeue with given capacity and growth 2
  231. /// </summary>
  232. /// <param name="capacity">the initial capacity of the collection</param>
  233. public Dequeue(int capacity)
  234. : this(capacity, 2.0)
  235. {
  236. }
  237. /// <summary>
  238. /// Create an empty Dequeue with given capacity and given growth
  239. /// </summary>
  240. /// <param name="capacity">The initial capacity of the collection</param>
  241. /// <param name="setGrowthFactor">The factor by which to grow the
  242. /// collection when the capacity is reached</param>
  243. public Dequeue(int capacity, double setGrowthFactor)
  244. {
  245. if (capacity < 1)
  246. {
  247. throw new ArgumentException("capacity", "must be at least 1.");
  248. }
  249. innerList = new T[capacity];
  250. growthFactor = setGrowthFactor;
  251. head = 0;
  252. tail = capacity - 1;
  253. /// <summary>
  254. /// Count
  255. /// </summary>
  256. count = 0;
  257. version = 0;
  258. }
  259. /// <summary>
  260. /// Create a new Dequeue as a copy of the given collection
  261. /// </summary>
  262. /// <param name="collection">The source collection</param>
  263. public Dequeue(ICollection<T> collection)
  264. : this(collection, collection.Count)
  265. {
  266. }
  267. /// <summary>
  268. /// Create a new Dequeue as a copy of the given collection and the
  269. /// given capacity.
  270. /// </summary>
  271. /// <param name="collection">The source collection</param>
  272. /// <param name="capacity">The capacity of the new Dequeue
  273. /// (must be bigger or equal as C.Count)</param>
  274. public Dequeue(ICollection<T> collection, int capacity)
  275. : this(capacity, 2.0)
  276. {
  277. tail = 0;
  278. EnqueueTailRange(collection);
  279. }
  280. #endregion
  281. #region ICloneable<Dequeue<T>> Members
  282. /// <summary>
  283. /// Standard implementation.
  284. /// </summary>
  285. /// <returns>A Dequeue with a shallow copy of this one.</returns>
  286. public Dequeue<T> Clone()
  287. {
  288. Dequeue<T> newDequeue = new Dequeue<T>(this, Capacity);
  289. newDequeue.growthFactor = growthFactor;
  290. newDequeue.version = Version;
  291. return newDequeue;
  292. }
  293. #endregion
  294. #region ICollection<T> Members
  295. /// <summary>
  296. /// Add. Not supported, do not call!
  297. /// </summary>
  298. /// <param name="item">Item to add</param>
  299. public void Add(T item)
  300. {
  301. throw new Exception("The method or operation is not implemented.");
  302. }
  303. /// <summary>
  304. /// Deletes all entries from the collection
  305. /// </summary>
  306. public void Clear()
  307. {
  308. head = tail = count = 0;
  309. version++;
  310. }
  311. /// <summary>
  312. /// Contains
  313. /// </summary>
  314. /// <param name="item">Item</param>
  315. /// <returns>True if the item was found, false otherwise.</returns>
  316. public bool Contains(T item)
  317. {
  318. for (int num = head; num < head + count; num++)
  319. {
  320. if (innerList[num % Capacity].Equals(item))
  321. {
  322. return true;
  323. }
  324. }
  325. // Not found
  326. return false;
  327. }
  328. /// <summary>
  329. /// Implementation of the ICollection.CopyTo function.
  330. /// </summary>
  331. /// <param name="array">Target array</param>
  332. /// <param name="arrayIndex">Start-Index in target array</param>
  333. public void CopyTo(T[] array, int arrayIndex)
  334. {
  335. if (array == null)
  336. {
  337. throw new ArgumentNullException("array");
  338. }
  339. if (arrayIndex < 0)
  340. {
  341. throw new ArgumentOutOfRangeException(
  342. "arrayIndex",
  343. "Must be at least zero: " + arrayIndex);
  344. }
  345. if (arrayIndex > count)
  346. {
  347. throw new Exception("arrayIndex=" + arrayIndex +
  348. " is out of range for target array (count=" + count +
  349. ")");
  350. }
  351. if (array.Length - arrayIndex < Count)
  352. {
  353. throw new ArgumentException("Array was to small!");
  354. }
  355. if (array.Rank > 1)
  356. {
  357. throw new ArgumentException("Array was multidimensional!");
  358. }
  359. for (int num = arrayIndex; num < array.Length; num++)
  360. {
  361. array[num] = innerList[(head + num) % innerList.Length];
  362. }
  363. }
  364. /// <summary>
  365. /// Remove. Do not call, this is not implemented!
  366. /// </summary>
  367. /// <param name="item">Item</param>
  368. /// <returns>
  369. /// True if removing the item succeeded, false otherwise.
  370. /// </returns>
  371. public bool Remove(T item)
  372. {
  373. throw new Exception("The method or operation is not implemented.");
  374. }
  375. #endregion
  376. #region IEnumerable Members
  377. /// <summary>
  378. /// System. collections. i enumerable. get enumerator
  379. /// </summary>
  380. /// <returns>System. collections. i enumerator</returns>
  381. IEnumerator
  382. IEnumerable.GetEnumerator()
  383. {
  384. return GetEnumerator();
  385. }
  386. #endregion
  387. #region IEnumerable<T> Members
  388. /// <summary>
  389. /// Standard implementation.
  390. /// </summary>
  391. /// <returns>A DequeueEnumerator on the current dequeue</returns>
  392. public IEnumerator<T> GetEnumerator()
  393. {
  394. for (int num = head; num < head + count; num++)
  395. {
  396. yield return innerList[num % innerList.Length];
  397. }
  398. }
  399. #endregion
  400. #region Equals (Public)
  401. /// <summary>
  402. /// Equals
  403. /// </summary>
  404. /// <param name="that">That</param>
  405. /// <returns>True if the other collection (that) is the same.</returns>
  406. public bool Equals(ICollection<T> that)
  407. {
  408. // Only compare if the reference is equal, we could also check
  409. // if the elements are equal, but who cares ...
  410. return this == that;
  411. }
  412. #endregion
  413. #region ContainsCount (Public)
  414. /// <summary>
  415. /// Contains count
  416. /// </summary>
  417. /// <param name="item">Item</param>
  418. /// <returns>Int</returns>
  419. public int ContainsCount(T item)
  420. {
  421. int contained = 0;
  422. for (int num = head; num < head + count; num++)
  423. {
  424. if (innerList[num % Capacity].Equals(item))
  425. {
  426. contained++;
  427. }
  428. }
  429. return contained;
  430. }
  431. #endregion
  432. #region ContainsAll (Public)
  433. /// <summary>
  434. /// Contains all
  435. /// </summary>
  436. /// <param name="items">Items to check</param>
  437. /// <returns>Returns true if all items are in this dequeue.</returns>
  438. public bool ContainsAll(IEnumerable<T> items)
  439. {
  440. foreach (T checkItem in items)
  441. {
  442. bool found = false;
  443. for (int num = head; num < head + count; num++)
  444. {
  445. if (innerList[num % Capacity].Equals(checkItem))
  446. {
  447. found = true;
  448. break;
  449. }
  450. }
  451. // Item not found, return false
  452. if (found == false)
  453. {
  454. return false;
  455. }
  456. }
  457. // All items passed, everything is in list
  458. return true;
  459. }
  460. #endregion
  461. #region Find (Public)
  462. /// <summary>
  463. /// Find. Do not call, this method is not implemented!
  464. /// </summary>
  465. /// <param name="item">Item</param>
  466. /// <returns>True if the item was found</returns>
  467. public bool Find(ref T item)
  468. {
  469. throw new Exception("The method or operation is not implemented.");
  470. }
  471. #endregion
  472. #region FindOrAdd (Public)
  473. /// <summary>
  474. /// Find or add. Do not call, this method is not implemented!
  475. /// </summary>
  476. /// <param name="item">Item</param>
  477. /// <returns>True if the item was found or could be added.</returns>
  478. public bool FindOrAdd(ref T item)
  479. {
  480. throw new Exception("The method or operation is not implemented.");
  481. }
  482. #endregion
  483. #region Update (Public)
  484. /// <summary>
  485. /// Update. Do not call, this method is not implemented!
  486. /// </summary>
  487. /// <param name="item">Item</param>
  488. /// <returns>True if the item was updated.</returns>
  489. public bool Update(T item)
  490. {
  491. throw new Exception("The method or operation is not implemented.");
  492. }
  493. #endregion
  494. #region UpdateOrAdd (Public)
  495. /// <summary>
  496. /// Update or add. Do not call, this method is not implemented!
  497. /// </summary>
  498. /// <param name="item">Item</param>
  499. /// <returns>True if the item was updated or added.</returns>
  500. public bool UpdateOrAdd(T item)
  501. {
  502. throw new Exception("The method or operation is not implemented.");
  503. }
  504. #endregion
  505. #region RemoveWithReturn (Public)
  506. /// <summary>
  507. /// Remove with return. Do not call, this method is not implemented!
  508. /// </summary>
  509. /// <param name="item">Item</param>
  510. /// <returns>True if the item was removed</returns>
  511. public bool RemoveWithReturn(ref T item)
  512. {
  513. throw new Exception("The method or operation is not implemented.");
  514. }
  515. #endregion
  516. #region RemoveAllCopies (Public)
  517. /// <summary>
  518. /// Remove all copies
  519. /// </summary>
  520. /// <param name="item">Item</param>
  521. public void RemoveAllCopies(T item)
  522. {
  523. throw new Exception("The method or operation is not implemented.");
  524. }
  525. #endregion
  526. #region RemoveAll (Public)
  527. /// <summary>
  528. /// Remove all
  529. /// </summary>
  530. /// <param name="items">Items</param>
  531. public void RemoveAll(IEnumerable<T> items)
  532. {
  533. throw new Exception("The method or operation is not implemented.");
  534. }
  535. #endregion
  536. #region RetainAll (Public)
  537. /// <summary>
  538. /// Retain all
  539. /// </summary>
  540. /// <param name="items">Items</param>
  541. public void RetainAll(IEnumerable<T> items)
  542. {
  543. throw new Exception("The method or operation is not implemented.");
  544. }
  545. #endregion
  546. #region AddAll (Public)
  547. /// <summary>
  548. /// Add all
  549. /// </summary>
  550. /// <param name="items">Items</param>
  551. public void AddAll(IEnumerable<T> items)
  552. {
  553. throw new Exception("The method or operation is not implemented.");
  554. }
  555. /// <summary>
  556. /// Add all
  557. /// </summary>
  558. /// <param name="items">Items</param>
  559. public void AddAll<U>(IEnumerable<U> items) where U : T
  560. {
  561. throw new Exception("The method or operation is not implemented.");
  562. }
  563. #endregion
  564. #region Check (Public)
  565. /// <summary>
  566. /// Check the queue. Do not call, this method is not implemented!
  567. /// </summary>
  568. /// <returns>True if the check succeeded, false otherwise.</returns>
  569. public bool Check()
  570. {
  571. throw new Exception("The method or operation is not implemented.");
  572. }
  573. #endregion
  574. #region ToArray (Public)
  575. /// <summary>
  576. /// To array
  577. /// </summary>
  578. /// <returns>Filled array with the same data as this dequeue</returns>
  579. public T[] ToArray()
  580. {
  581. T[] ret = new T[count];
  582. CopyTo(ret, 0);
  583. return ret;
  584. }
  585. #endregion
  586. #region EnqueueHead (Public)
  587. /// <summary>
  588. /// Add the given object to the collections head
  589. /// </summary>
  590. /// <param name="value">The object to enqueue</param>
  591. public void EnqueueHead(T value)
  592. {
  593. if (Count == Capacity)
  594. {
  595. SetSize((int)(Capacity * GrowthFactor));
  596. }
  597. head--;
  598. if (head < 0)
  599. {
  600. head += Capacity;
  601. }
  602. innerList[head] = value;
  603. count++;
  604. version++;
  605. }
  606. #endregion
  607. #region EnqueueTail (Public)
  608. /// <summary>
  609. /// Add the given object to the collections tail
  610. /// </summary>
  611. /// <param name="value">The object to enqueue</param>
  612. public void EnqueueTail(T value)
  613. {
  614. if (Count == Capacity)
  615. {
  616. SetSize((int)(Capacity * GrowthFactor));
  617. }
  618. tail++;
  619. tail %= Capacity;
  620. innerList[tail] = value;
  621. count++;
  622. version++;
  623. }
  624. #endregion
  625. #region DequeueHead (Public)
  626. /// <summary>
  627. /// Retrieve and remove the current head
  628. /// </summary>
  629. /// <returns>The removed object</returns>
  630. public T DequeueHead()
  631. {
  632. if (Count == 0)
  633. {
  634. throw new Exception("Dequeue was empty!");
  635. }
  636. T r = innerList[head];
  637. head++;
  638. head %= Capacity;
  639. count--;
  640. version++;
  641. return r;
  642. }
  643. #endregion
  644. #region DequeueTail (Public)
  645. /// <summary>
  646. /// Retrieve and remove the current tail
  647. /// </summary>
  648. /// <returns>The removed object</returns>
  649. public T DequeueTail()
  650. {
  651. if (Count == 0)
  652. {
  653. throw new Exception("Dequeue was empty!");
  654. }
  655. T r = innerList[tail];
  656. tail--;
  657. if (tail < 0)
  658. {
  659. tail += Capacity;
  660. }
  661. count--;
  662. version++;
  663. return r;
  664. }
  665. #endregion
  666. #region EnqueueTailRange (Public)
  667. /// <summary>
  668. /// Add the given collection to the dequeues tail
  669. /// </summary>
  670. /// <param name="collection">The source collection</param>
  671. public void EnqueueTailRange(ICollection<T> collection)
  672. {
  673. int cap = Capacity;
  674. while (cap < collection.Count)
  675. {
  676. cap = (int)(cap * GrowthFactor);
  677. }
  678. if (cap > Capacity)
  679. {
  680. SetSize(cap);
  681. }
  682. foreach (T obj in collection)
  683. {
  684. EnqueueTail(obj);
  685. }
  686. }
  687. #endregion
  688. #region EnqueueHeadRange (Public)
  689. /// <summary>
  690. /// Add the given collection to the dequeues head.
  691. /// To preserve the order in the collection, the entries are
  692. /// added in revers order.
  693. /// </summary>
  694. /// <param name="collection">The source collection</param>
  695. public void EnqueueHeadRange(ICollection<T> collection)
  696. {
  697. int cap = Capacity;
  698. while (cap < collection.Count)
  699. {
  700. cap = (int)(cap * GrowthFactor);
  701. }
  702. if (cap > Capacity)
  703. {
  704. SetSize(cap);
  705. }
  706. List<T> tempList = new List<T>(collection);
  707. tempList.Reverse();
  708. foreach (T obj in tempList)
  709. {
  710. EnqueueHead(obj);
  711. }
  712. }
  713. #endregion
  714. #region TrimToSize (Public)
  715. /// <summary>
  716. /// Sets the capacity to Count.
  717. /// </summary>
  718. public void TrimToSize()
  719. {
  720. SetSize(Count);
  721. }
  722. #endregion
  723. #region CopyTo (Public)
  724. /// <summary>
  725. /// Implementation of the ICollection.CopyTo function.
  726. /// </summary>
  727. /// <param name="array">Target array</param>
  728. /// <param name="index">Start-Index in target array</param>
  729. public void CopyTo(Array array, int index)
  730. {
  731. if (array == null)
  732. {
  733. throw new ArgumentNullException("array");
  734. }
  735. if (index < 0)
  736. {
  737. throw new ArgumentOutOfRangeException("index",
  738. "Must be at least zero: " + index);
  739. }
  740. if (array.Length - index < Count)
  741. {
  742. throw new ArgumentException("Array was to small!");
  743. }
  744. if (array.Rank > 1)
  745. {
  746. throw new ArgumentException("Array was multidimensional!");
  747. }
  748. for (int num = 0; num < Count; num++)
  749. {
  750. array.SetValue(this[num], num + index);
  751. }
  752. }
  753. #endregion
  754. #region Methods (Private)
  755. #region SetSize
  756. /// <summary>
  757. /// Sets the collections capacity to newSize
  758. /// </summary>
  759. /// <param name="newSize">the new collection size
  760. /// (must be &gt;= Count)</param>
  761. protected void SetSize(int newSize)
  762. {
  763. if (newSize < Count)
  764. {
  765. throw new ArgumentException("New Size was smaller than Count!");
  766. }
  767. T[] newInnerList = new T[newSize];
  768. for (int num = 0; num < Count; num++)
  769. {
  770. newInnerList[num] = this[num];
  771. }
  772. head = 0;
  773. tail = Count;
  774. innerList = newInnerList;
  775. version++;
  776. }
  777. #endregion
  778. #endregion
  779. }
  780. /// <summary>
  781. /// Dequeue tests, needs to be an extra class because Dequeue is generic.
  782. /// </summary>
  783. internal class DequeueTests
  784. {
  785. #region TestDequeueGenericPerformance (Static)
  786. /// <summary>
  787. /// Test dequeue generic performance
  788. /// </summary>
  789. [Test, Category("LongRunning")]
  790. public static void TestDequeueGenericPerformance()
  791. {
  792. /*finish this when the Profiler in Delta.Utilities is re-enabled
  793. // Run 10 million loops
  794. const int NumOfElementsToAdd = 10000000;
  795. Profiler.BeginSection("Test linked lists", "Dequeue");
  796. Dequeue dequeue = new Dequeue();
  797. for (int num = 0; num < NumOfElementsToAdd; num++)
  798. {
  799. dequeue.EnqueueHead(num);
  800. if (num > 10)
  801. //Console.WriteLine(
  802. dequeue.DequeueTail();
  803. } // for (num)
  804. Profiler.Add("Dequeue with generics");
  805. Dequeue<int> dequeueGeneric = new Dequeue<int>();
  806. for (int num = 0; num < NumOfElementsToAdd; num++)
  807. {
  808. dequeueGeneric.EnqueueHead(num);
  809. if (num > 10)
  810. //Console.WriteLine(
  811. dequeueGeneric.DequeueTail();
  812. } // for (num)
  813. Profiler.EndSection();
  814. Console.WriteLine(Profiler.GetProfilerText());
  815. // Results for 10000000 (10 mio) elements to add:
  816. // Profiler (Total time: 1,48s)
  817. // Dequeue: 949,33ms (64,1%)
  818. // Dequeue with generics: 531,11ms (35,9%)
  819. */
  820. }
  821. #endregion
  822. #region TestEnqueueHead
  823. /// <summary>
  824. /// Test enqueue head
  825. /// </summary>
  826. [Test]
  827. public void TestEnqueueHead()
  828. {
  829. Dequeue<int> dequeue = new Dequeue<int>();
  830. dequeue.EnqueueHead(1);
  831. dequeue.EnqueueHead(2);
  832. dequeue.EnqueueHead(3);
  833. dequeue.EnqueueHead(5);
  834. Assert.Equal(5, dequeue.DequeueHead());
  835. Assert.Equal(3, dequeue.DequeueHead());
  836. Assert.Equal(1, dequeue.DequeueTail());
  837. Assert.Equal(1, dequeue.Count);
  838. }
  839. #endregion
  840. #region TestEnqueueTail
  841. /// <summary>
  842. /// Test enqueue tail
  843. /// </summary>
  844. [Test]
  845. public void TestEnqueueTail()
  846. {
  847. Dequeue<int> dequeue = new Dequeue<int>();
  848. dequeue.EnqueueTail(1);
  849. dequeue.EnqueueTail(2);
  850. dequeue.EnqueueTail(3);
  851. dequeue.EnqueueTail(5);
  852. Assert.Equal(5, dequeue.DequeueTail());
  853. Assert.Equal(3, dequeue.DequeueTail());
  854. Assert.Equal(1, dequeue.DequeueHead());
  855. Assert.Equal(1, dequeue.Count);
  856. }
  857. #endregion
  858. }
  859. }