最近在实习期间学习《C#高级编程》看到了书上讲到多优先级队列,产生了兴趣,然后在网上百度了许多C#的多优先级队列,基本都是用数组什么的,而书上使用的是双向链表。但是书上的优先队列没有写全,我通过自己的琢磨理解之后写了一个优先队列类。希望各位大佬帮忙看看,多谢。同时,希望能够对一些需要的人产生一丢丢作用。
话不多说,上代码。
这是优先队列的类
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PriorityQueueWinform
{
class PriorityQueue<T> : IEnumerable<PriorityItem<T>> where T : IComparable<T>, IEquatable<T>
{
//创建链表和节点集合
private LinkedList<PriorityItem<T>> _linkedList;
private List<LinkedListNode<PriorityItem<T>>> _firstNodeList;
private List<LinkedListNode<PriorityItem<T>>> _lastNodeList;
//返回多优先级队列的长度
public int Count { get { return _linkedList.Count; } }
//返回最大优先级
public int MaxPriority { get; private set; }
//返回优先级是否从大到小
public bool IsDesc { get; private set; }
//重载构造函数
public PriorityQueue() : this(10, true)
{ }
public PriorityQueue(int priority) : this(priority, true)
{ }
public PriorityQueue(bool isDesc) : this(10, isDesc)
{ }
public PriorityQueue(int priority, bool isDesc)
{
MaxPriority = priority;
IsDesc = isDesc;
_linkedList = new LinkedList<PriorityItem<T>>();
_firstNodeList = new List<LinkedListNode<PriorityItem<T>>>(priority);
_lastNodeList = new List<LinkedListNode<PriorityItem<T>>>(priority);
for (int i = 0; i < priority; i++)
{
_firstNodeList.Add(new LinkedListNode<PriorityItem<T>>(new PriorityItem<T>(default(T), -1)));
_lastNodeList.Add(new LinkedListNode<PriorityItem<T>>(new PriorityItem<T>(default(T), -1)));
}
}
/// <summary>
/// 添加值为value,优先级为priority的元素
/// </summary>
/// <param name="value">值</param>
/// <param name="priority">优先级</param>
public void Enqueue(T value, int priority)
{
if (value == null) throw new ArgumentNullException($"{nameof(value)}为空!");
if (priority < 0 || priority > MaxPriority) throw new ArgumentOutOfRangeException($"{nameof(priority)} 超出范围!");
PriorityItem<T> item = new PriorityItem<T>(value, priority);
LinkedListNode<PriorityItem<T>> node = _lastNodeList[priority];
if (_linkedList.Find(item) != null) throw new ArgumentException("此节点已存在");
//如果当前节点中有元素
if (node.Value.Priority >= 0)
{
_linkedList.AddAfter(node, item);
_lastNodeList[priority] = node.Next;
}
else
{
//如果优先级从大到小则找比将添加节点的优先级大的第一个节点
if (IsDesc)
node = _lastNodeList.Find(n => n.Value.Priority > priority);
else//否则找比将添加节点的优先级小的最后一个节点
node = _lastNodeList.FindLast(n => n.Value.Priority < priority & n.Value.Priority >= 0);
//即寻找离将添加节点前面最近的节点
//如果找不到节点
if (node != default(LinkedListNode<PriorityItem<T>>) && node != null)
{
_linkedList.AddAfter(node, item);
_firstNodeList[priority] = node.Next;
_lastNodeList[priority] = node.Next;
}
//如果找到
else
{
_linkedList.AddFirst(item);
_firstNodeList[priority] = _linkedList.First;
_lastNodeList[priority] = _linkedList.First;
}
}
}
/// <summary>
/// 输出队列第一个元素并删除之
/// </summary>
/// <returns>第一个元素</returns>
public T Dequeue()
{
if (_linkedList.Count == 0)
return default(T);
LinkedListNode<PriorityItem<T>> first = _linkedList.First;
int priority = first.Value.Priority;
//如果这是该优先级的最后一个元素
if (_firstNodeList[priority] == _lastNodeList[priority])
{
_firstNodeList[priority] = new LinkedListNode<PriorityItem<T>>(new PriorityItem<T>(default(T), -1));
_lastNodeList[priority] = new LinkedListNode<PriorityItem<T>>(new PriorityItem<T>(default(T), -1));
}
else
{
_firstNodeList[priority] = _firstNodeList[priority].Next;
}
_linkedList.RemoveFirst();
return first.Value.Value;
}
/// <summary>
/// 删除指定元素
/// </summary>
/// <param name="item"></param>
public void Delete(PriorityItem<T> item)
{
LinkedListNode<PriorityItem<T>> node = _linkedList.Find(item);
int priority = node.Value.Priority;
if (_lastNodeList[priority] == _firstNodeList[priority])
{
_firstNodeList[priority] = new LinkedListNode<PriorityItem<T>>(new PriorityItem<T>(default(T), -1));
_lastNodeList[priority] = new LinkedListNode<PriorityItem<T>>(new PriorityItem<T>(default(T), -1));
}
else if (node == _firstNodeList[priority])
_firstNodeList[priority] = _firstNodeList[priority].Next;
else if (node == _lastNodeList[priority])
_lastNodeList[priority] = _lastNodeList[priority].Previous;
_linkedList.Remove(node);
}
/// <summary>
/// 搜索优先级为priority的节点
/// </summary>
/// <param name="priority">优先级</param>
/// <returns>该优先级的所有节点</returns>
public IEnumerable<PriorityItem<T>> SelectByPriority(int priority)
{
LinkedListNode<PriorityItem<T>> node = _firstNodeList[priority];
while (node.Value.Priority != -1 && node.Previous != _lastNodeList[priority] && node.Next != null)
{
yield return node.Value;
node = node.Next;
}
}
IEnumerator<PriorityItem<T>> IEnumerable<PriorityItem<T>>.GetEnumerator()
{
foreach (var i in _linkedList)
yield return i;
}
public IEnumerator GetEnumerator()
{
foreach (var i in _linkedList)
yield return i;
}
}
}
这是优先队列中节点value的类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PriorityQueueWinform
{
class PriorityItem<T> : IEquatable<PriorityItem<T>> where T : IComparable<T>, IEquatable<T>
{
private T _value;
private int _priority;
public T Value
{
get
{
return _value;
}
}
public int Priority
{
get
{
return _priority;
}
}
public PriorityItem(T value, int priority)
{
_value = value;
_priority = priority;
}
public override string ToString()
{
return $"Priority:{_priority} Value:{_value}";
}
public bool Equals(PriorityItem<T> other)
{
return _priority == other.Priority && Value.Equals(other.Value);
}
}
}