From 99db0bfe4b8a06651f765ba825dae0d65d9bb200 Mon Sep 17 00:00:00 2001 From: JohannesMP <662874+JohannesMP@users.noreply.github.com> Date: Sun, 25 Jul 2021 19:00:50 -0700 Subject: [PATCH 1/6] Add missing summary xml comment tag --- Priority Queue/SimplePriorityQueue.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Priority Queue/SimplePriorityQueue.cs b/Priority Queue/SimplePriorityQueue.cs index f37a9d1..fc3c5c8 100644 --- a/Priority Queue/SimplePriorityQueue.cs +++ b/Priority Queue/SimplePriorityQueue.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; @@ -372,10 +372,12 @@ public TPriority GetPriority(TItem item) } #region Try* methods for multithreading + /// /// Get the head of the queue, without removing it (use TryDequeue() for that). /// Useful for multi-threading, where the queue may become empty between calls to Contains() and First /// Returns true if successful, false otherwise /// O(1) + /// public bool TryFirst(out TItem first) { if (_queue.Count > 0) From c39e2a9da9ecef9b9e187cd1ab4bf11c9f00d714 Mon Sep 17 00:00:00 2001 From: JohannesMP <662874+JohannesMP@users.noreply.github.com> Date: Sun, 25 Jul 2021 19:04:14 -0700 Subject: [PATCH 2/6] Add SimplePriorityQueue.TryDequeue TryRemove overloads that also output the priority of the removed node --- Priority Queue/SimplePriorityQueue.cs | 75 ++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/Priority Queue/SimplePriorityQueue.cs b/Priority Queue/SimplePriorityQueue.cs index fc3c5c8..8351438 100644 --- a/Priority Queue/SimplePriorityQueue.cs +++ b/Priority Queue/SimplePriorityQueue.cs @@ -423,7 +423,36 @@ public bool TryDequeue(out TItem first) } /// - /// Attempts to remove an item from the queue. The item does not need to be the head of the queue. + /// Removes the head of the queue (node with minimum priority; ties are broken by order of insertion), + /// and sets it to first along with its priority. + /// Useful for multi-threading, where the queue may become empty between calls to Contains(), GetPriority() and Dequeue() + /// Returns true if successful; false if queue was empty + /// O(log n) + /// + public bool TryDequeue(out TItem first, out TPriority firstPriority) + { + if (_queue.Count > 0) + { + lock (_queue) + { + if (_queue.Count > 0) + { + SimpleNode node = _queue.Dequeue(); + first = node.Data; + firstPriority = node.Priority; + RemoveFromNodeCache(node); + return true; + } + } + } + + first = default(TItem); + firstPriority = default(TPriority); + return false; + } + + /// + /// Attempts to remove an item from the queue. The item does not need to be the head of the queue. /// Useful for multi-threading, where the queue may become empty between calls to Contains() and Remove() /// Returns true if the item was successfully removed, false if it wasn't in the queue. /// If multiple copies of the item are enqueued, only the first one is removed. @@ -462,6 +491,50 @@ public bool TryRemove(TItem item) } } + /// + /// Attempts to remove an item from the queue. The item does not need to be the head of the queue. + /// Useful for multi-threading, where the queue may become empty between calls to Contains(), GetPriority() and Remove() + /// Returns true if the item was successfully removed, false if it wasn't in the queue. + /// Assigns priority to priority of removed item if successfully removed. + /// If multiple copies of the item are enqueued, only the first one is removed. + /// O(log n) + /// + public bool TryRemove(TItem item, out TPriority priority) + { + lock (_queue) + { + SimpleNode removeMe; + IList nodes; + if (item == null) + { + if (_nullNodesCache.Count == 0) + { + priority = default(TPriority); + return false; + } + removeMe = _nullNodesCache[0]; + nodes = _nullNodesCache; + } + else + { + if (!_itemToNodesCache.TryGetValue(item, out nodes)) + { + priority = default(TPriority); + return false; + } + removeMe = nodes[0]; + if (nodes.Count == 1) + { + _itemToNodesCache.Remove(item); + } + } + _queue.Remove(removeMe); + nodes.Remove(removeMe); + priority = removeMe.Priority; + return true; + } + } + /// /// Call this method to change the priority of an item. /// Useful for multi-threading, where the queue may become empty between calls to Contains() and UpdatePriority() From 4eb72d54d5fd9708a833f4ebe7851198433b9a31 Mon Sep 17 00:00:00 2001 From: JohannesMP <662874+JohannesMP@users.noreply.github.com> Date: Sun, 25 Jul 2021 19:05:30 -0700 Subject: [PATCH 3/6] Add SimplePriorityQueue.TryFirst overload that also outputs the priority of the node --- Priority Queue/SimplePriorityQueue.cs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Priority Queue/SimplePriorityQueue.cs b/Priority Queue/SimplePriorityQueue.cs index 8351438..cf5ff5d 100644 --- a/Priority Queue/SimplePriorityQueue.cs +++ b/Priority Queue/SimplePriorityQueue.cs @@ -396,6 +396,32 @@ public bool TryFirst(out TItem first) return false; } + /// + /// Get the head of the queue, without removing it (use TryDequeue() for that) as well as its priority. + /// Useful for multi-threading, where the queue may become empty between calls to Contains(), First and GetPriority() + /// Returns true if successful, false otherwise + /// O(1) + /// + public bool TryFirst(out TItem first, out TPriority firstPriority) + { + if (_queue.Count > 0) + { + lock (_queue) + { + if (_queue.Count > 0) + { + first = _queue.First.Data; + firstPriority = _queue.First.Priority; + return true; + } + } + } + + first = default(TItem); + firstPriority = default(TPriority); + return false; + } + /// /// Removes the head of the queue (node with minimum priority; ties are broken by order of insertion), and sets it to first. /// Useful for multi-threading, where the queue may become empty between calls to Contains() and Dequeue() From d358f5b7659ff4feb22980e77a309243a216a184 Mon Sep 17 00:00:00 2001 From: JohannesMP <662874+JohannesMP@users.noreply.github.com> Date: Sun, 25 Jul 2021 19:27:36 -0700 Subject: [PATCH 4/6] Add Tests for SimplePriorityQueue.TryDequeue with priority out parameter --- .../SimplePriorityQueueTests.cs | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/Priority Queue Tests/SimplePriorityQueueTests.cs b/Priority Queue Tests/SimplePriorityQueueTests.cs index 14e3a47..ab00b73 100644 --- a/Priority Queue Tests/SimplePriorityQueueTests.cs +++ b/Priority Queue Tests/SimplePriorityQueueTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using NUnit.Framework; using Priority_Queue; @@ -425,6 +425,16 @@ public void TestTryDequeueEmptyQueue() Assert.IsNull(first); } + [Test] + public void TestTryDequeueEmptyQueueWithPriorityOut() + { + Node first; + float firstPriority; + Assert.IsFalse(Queue.TryDequeue(out first, out firstPriority)); + Assert.IsNull(first); + Assert.AreEqual(0, firstPriority); + } + [Test] public void TestTryDequeueWithItems() { @@ -438,6 +448,21 @@ public void TestTryDequeueWithItems() Assert.AreEqual(0, Queue.Count); } + [Test] + public void TestTryDequeueWithItemsWithPriorityOut() + { + Node node = new Node(1); + Node first; + float firstPriority; + + Enqueue(node); + + Assert.IsTrue(Queue.TryDequeue(out first, out firstPriority)); + Assert.AreEqual(node, first); + Assert.AreEqual(0, Queue.Count); + Assert.AreEqual(node.Priority, firstPriority); + } + [Test] public void TestTryRemoveEmptyQueue() { From 6d00bccb93df65f7a85a89d2b0ddd9afce34a3e6 Mon Sep 17 00:00:00 2001 From: JohannesMP <662874+JohannesMP@users.noreply.github.com> Date: Sun, 25 Jul 2021 19:29:38 -0700 Subject: [PATCH 5/6] Add Tests for SimplePriorityQueue.TryRemove with priority out parameter --- .../SimplePriorityQueueTests.cs | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/Priority Queue Tests/SimplePriorityQueueTests.cs b/Priority Queue Tests/SimplePriorityQueueTests.cs index ab00b73..17965d5 100644 --- a/Priority Queue Tests/SimplePriorityQueueTests.cs +++ b/Priority Queue Tests/SimplePriorityQueueTests.cs @@ -471,6 +471,16 @@ public void TestTryRemoveEmptyQueue() Assert.IsFalse(Queue.TryRemove(node)); } + [Test] + public void TestTryRemoveEmptyQueueWithPriorityOut() + { + Node node = new Node(1); + float priority; + + Assert.IsFalse(Queue.TryRemove(node, out priority)); + Assert.AreEqual(0, priority); + } + [Test] public void TestTryRemoveItemInQueue() { @@ -498,6 +508,41 @@ public void TestTryRemoveItemInQueue() Assert.IsFalse(Queue.TryRemove(node1)); } + [Test] + public void TestTryRemoveItemInQueueWithPriorityOut() + { + Node node1 = new Node(1); + Node node2 = new Node(2); + Node node3 = new Node(3); + + Enqueue(node1); + Enqueue(node2); + Enqueue(node3); + + float priority; + + Assert.IsTrue(Queue.Contains(node2)); + Assert.IsTrue(Queue.TryRemove(node2, out priority)); + Assert.AreEqual(node2.Priority, priority); + Assert.IsFalse(Queue.Contains(node2)); + Assert.IsFalse(Queue.TryRemove(node2, out priority)); + Assert.AreEqual(0, priority); + + Assert.IsTrue(Queue.Contains(node3)); + Assert.IsTrue(Queue.TryRemove(node3, out priority)); + Assert.AreEqual(node3.Priority, priority); + Assert.IsFalse(Queue.Contains(node3)); + Assert.IsFalse(Queue.TryRemove(node3, out priority)); + Assert.AreEqual(0, priority); + + Assert.IsTrue(Queue.Contains(node1)); + Assert.IsTrue(Queue.TryRemove(node1, out priority)); + Assert.AreEqual(node1.Priority, priority); + Assert.IsFalse(Queue.Contains(node1)); + Assert.IsFalse(Queue.TryRemove(node1, out priority)); + Assert.AreEqual(0, priority); + } + [Test] public void TestTryRemoveItemNotInQueue() { @@ -511,6 +556,22 @@ public void TestTryRemoveItemNotInQueue() Assert.IsFalse(Queue.TryRemove(node3)); } + [Test] + public void TestTryRemoveItemNotInQueueWithPriorityOut() + { + Node node1 = new Node(1); + Node node2 = new Node(2); + Node node3 = new Node(3); + + Enqueue(node1); + Enqueue(node2); + + float priority; + + Assert.IsFalse(Queue.TryRemove(node3, out priority)); + Assert.AreEqual(0, priority); + } + [Test] public void TestTryUpdatePriorityEmptyQueue() { From e0f3b9683585b60abc2fc7ba18df013f9bf4f846 Mon Sep 17 00:00:00 2001 From: JohannesMP <662874+JohannesMP@users.noreply.github.com> Date: Sun, 25 Jul 2021 19:37:49 -0700 Subject: [PATCH 6/6] Add Tests for SimplePriorityQueue.TryFirst with priority out parameter --- .../SimplePriorityQueueTests.cs | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Priority Queue Tests/SimplePriorityQueueTests.cs b/Priority Queue Tests/SimplePriorityQueueTests.cs index 17965d5..4f1cb58 100644 --- a/Priority Queue Tests/SimplePriorityQueueTests.cs +++ b/Priority Queue Tests/SimplePriorityQueueTests.cs @@ -404,6 +404,16 @@ public void TestTryFirstEmptyQueue() Assert.IsNull(first); } + [Test] + public void TestTryFirstEmptyQueueWithPriorityOut() + { + Node first; + float firstPriority; + Assert.IsFalse(Queue.TryFirst(out first, out firstPriority)); + Assert.IsNull(first); + Assert.AreEqual(0, firstPriority); + } + [Test] public void TestTryFirstWithItems() { @@ -417,6 +427,21 @@ public void TestTryFirstWithItems() Assert.AreEqual(1, Queue.Count); } + [Test] + public void TestTryFirstWithItemsWithPriorityOut() + { + Node node = new Node(1); + Node first; + float firstPriority; + + Enqueue(node); + + Assert.IsTrue(Queue.TryFirst(out first, out firstPriority)); + Assert.AreEqual(node, first); + Assert.AreEqual(1, Queue.Count); + Assert.AreEqual(node.Priority, firstPriority); + } + [Test] public void TestTryDequeueEmptyQueue() {