{"id":45,"date":"2008-10-20T00:00:00","date_gmt":"2008-10-20T00:00:00","guid":{"rendered":"http:\/\/bloodforge.com\/?p=45"},"modified":"2020-02-20T02:05:01","modified_gmt":"2020-02-20T02:05:01","slug":"c-priority-queue-implementation-for-silverlight","status":"publish","type":"post","link":"https:\/\/bloodforge.azurewebsites.net\/index.php\/2008\/10\/20\/c-priority-queue-implementation-for-silverlight\/","title":{"rendered":"C# Priority Queue Implementation for Silverlight"},"content":{"rendered":"\n<p>While writing some code for Silverlight, I realized that Silverlight does not include a PriorityQueue implementation in their libraries.&nbsp; I searched around, but I couldn&#8217;t find any code that I thought was decent, so I wrote up something pretty quick.&nbsp; I&#8217;ll be testing this some more in the near future, but for now, I think it has the basics.&nbsp; This should be fairly quick for large collections, as the enqueue is logarithmic, while the dequeue is pretty much as fast as it can be.<\/p>\n\n\n\n<p>The queue uses generics for both the priority and the data that is being queued. The only thing to keep in mind is that if you&#8217;re creating your own type for priority, it must implement IComparable.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>    using System;\n    using System.Collections.Generic; \n     \n    namespace bloodforge\n    {\n        public class PriorityQueue&lt;P, T>\n            where P : System.IComparable&lt;P>\n        {\n            protected List&lt;Queue&lt;PriorityItem&lt;P, T>>> _queues;\n           protected int _count; \n    \n           public PriorityQueue()\n           {\n               _queues = new List&lt;Queue&lt;PriorityItem&lt;P, T>>>();\n               _count = 0;\n           } \n    \n           \/\/\/ &lt;summary>\n           \/\/\/ Add an item to the priority queue\n           \/\/\/ &lt;\/summary>\n           public void Enqueue(P priority, T data)\n           {\n               if (_count == 0)\n               {\n                   Queue&lt;PriorityItem&lt;P, T>> NewQueue = new Queue&lt;PriorityItem&lt;P, T>>();\n                   NewQueue.Enqueue(new PriorityItem&lt;P, T>(priority, data));\n                   _queues.Add(NewQueue);\n               }\n               else\n               {\n                   QueueInsert(priority, data, 0, _queues.Count - 1);\n               } \n    \n               _count++;\n           } \n    \n           \/\/\/ &lt;summary>\n           \/\/\/ Helper method for Enqueue\n           \/\/\/ &lt;\/summary>\n           private void QueueInsert(P priority, T data, int qLo, int qHi)\n           {\n               if (qLo == qHi)\n               {\n                   \/\/ There is only one item left to compare.\n                   \/\/ Need to decide where this item belongs in relation to the last item.\n                   if (_queues&#91;qLo].Peek().Priority.CompareTo(priority) &lt; 0)\n                   {\n                       Queue&lt;PriorityItem&lt;P, T>> NewQueue = new Queue&lt;PriorityItem&lt;P, T>>();\n                       NewQueue.Enqueue(new PriorityItem&lt;P, T>(priority, data));\n                       _queues.Insert(qLo, NewQueue);\n                       return;\n                   }\n                   else if (_queues&#91;qLo].Peek().Priority.CompareTo(priority) > 0)\n                   {\n                       Queue&lt;PriorityItem&lt;P, T>> NewQueue = new Queue&lt;PriorityItem&lt;P, T>>();\n                       NewQueue.Enqueue(new PriorityItem&lt;P, T>(priority, data));\n                       _queues.Insert(qLo + 1, NewQueue);\n                       return;\n                   }\n                   else\n                   {\n                       _queues&#91;qLo].Enqueue(new PriorityItem&lt;P, T>(priority, data));\n                       return;\n                   }\n               }\n               else\n               {\n                   \/\/ Get the middle item from the queue and see if we\n                   \/\/ need to go to the first or second half of the queues list\n                   int qMid = Convert.ToInt32(Math.Floor((qLo + qHi) \/ 2));\n                   if (_queues&#91;qMid].Peek().Priority.CompareTo(priority) &lt; 0)\n                   {\n                       \/\/ This item belongs in the upper half of the range\n                       QueueInsert(priority, data, qLo, qMid);\n                       return;\n                   }\n                   else if (_queues&#91;qMid].Peek().Priority.CompareTo(priority) > 0)\n                   {\n                       \/\/ This item belongs in the lower half of the range\n                       QueueInsert(priority, data, qMid + 1, qHi);\n                       return;\n                   }\n                   else\n                   {\n                       \/\/ we got lucky, the middle item is of the same priority\n                       _queues&#91;qMid].Enqueue(new PriorityItem&lt;P, T>(priority, data));\n                       return;\n                   }\n               }\n           } \n    \n           \/\/\/ &lt;summary>\n           \/\/\/ Remove the top item from the queue\n           \/\/\/ &lt;\/summary>\n           public T Dequeue()\n           {\n               if (_queues.Count == 0)\n               {\n                   \/\/ There are no items in the priority queue\n                  return default(T);\n              } \n   \n              \/\/ Get the first item from the first queue\n              T data = _queues&#91;0].Dequeue().Data; \n   \n              if (_queues&#91;0].Count == 0)\n              {\n                  \/\/ If the queue at the top priority is empty, remove it\n                  _queues.RemoveAt(0);\n              } \n   \n              _count--; \n   \n              return data; \n   \n          } \n   \n          \/\/\/ &lt;summary>\n          \/\/\/ Retrieves the top item from the queue without removing it\n          \/\/\/ &lt;\/summary>\n          public T Peek()\n          {\n              if (_queues.Count > 0)\n              {\n                    return _queues&#91;0].Peek().Data;\n              }\n              else return default(T);\n          } \n   \n          \/\/\/ &lt;summary>\n          \/\/\/ Gets the number of items in the priority queue\n          \/\/\/ &lt;\/summary>\n          public int Count\n          {\n              get\n              {\n                  return _count;\n              }\n          } \n   \n          \/\/\/ &lt;summary>\n          \/\/\/ Returns a string representation of the queue\n          \/\/\/ &lt;\/summary>\n          public override string ToString()\n          {\n              string val = string.Empty;\n              foreach(Queue&lt;PriorityItem&lt;P, T>> queue in _queues)\n              {\n                  PriorityItem&lt;P, T>&#91;] items = queue.ToArray();\n                  foreach (PriorityItem&lt;P, T> item in items)\n                  {\n                      val += string.Format(\" &#91; {0} ] \", item.Data.ToString());\n                  }\n              }\n              return val.TrimEnd(',');\n          }\n      } \n   \n      public class PriorityItem&lt;P, T>\n          where P : System.IComparable&lt;P>\n      {\n          public P Priority;\n          public T Data; \n   \n          public PriorityItem(P priority, T data)\n          {\n              this.Priority = priority;\n              this.Data = data;\n          }\n      }\n  } <\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>While writing some code for Silverlight, I realized that Silverlight does not include a PriorityQueue implementation in their libraries.&nbsp; I searched around, but I couldn&#8217;t find any code that I thought was decent, so I wrote up something pretty quick.&nbsp; I&#8217;ll be testing this some more in the near future, but for now, I think [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3],"tags":[],"_links":{"self":[{"href":"https:\/\/bloodforge.azurewebsites.net\/index.php\/wp-json\/wp\/v2\/posts\/45"}],"collection":[{"href":"https:\/\/bloodforge.azurewebsites.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bloodforge.azurewebsites.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bloodforge.azurewebsites.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bloodforge.azurewebsites.net\/index.php\/wp-json\/wp\/v2\/comments?post=45"}],"version-history":[{"count":1,"href":"https:\/\/bloodforge.azurewebsites.net\/index.php\/wp-json\/wp\/v2\/posts\/45\/revisions"}],"predecessor-version":[{"id":46,"href":"https:\/\/bloodforge.azurewebsites.net\/index.php\/wp-json\/wp\/v2\/posts\/45\/revisions\/46"}],"wp:attachment":[{"href":"https:\/\/bloodforge.azurewebsites.net\/index.php\/wp-json\/wp\/v2\/media?parent=45"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bloodforge.azurewebsites.net\/index.php\/wp-json\/wp\/v2\/categories?post=45"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bloodforge.azurewebsites.net\/index.php\/wp-json\/wp\/v2\/tags?post=45"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}