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()
{