c# - C#中的优先级队列实现

标签 c# .net data-structures

<分区>

我正在尝试使用 SortedDictionary 实现优先级队列机制,我想获得有关我当前实现的建议。

我的实现如下:

public class PriorityQueue
{
    private Object lockObj;
    private SortedDictionary<PQMsgPriority, Queue<PQMessage>> messageDictionary; 

    public PriorityQueue()
    {
        lockObj = new object();
        messageDictionary = new SortedDictionary<PQMsgPriority, Queue<PQMessage>>();
    }

    public void Enqueue(PQMessage item)
    {
        lock (lockObj)
        {
            if(item != null && item.MsgPriority == PQMsgPriority.None)
            {
                if (messageDictionary.ContainsKey(item.MsgPriority))
                {
                    Queue<PQMessage> dataList = messageDictionary[item.MsgPriority];
                    dataList.Enqueue(item);
                    messageDictionary[item.MsgPriority] = dataList;
                }
                else
                {
                    Queue<PQMessage> dataList = new Queue<PQMessage>();
                    dataList.Enqueue(item);
                    messageDictionary.Add(item.MsgPriority, dataList);
                }
            }
        }
    }

    public PQMessage Dequeue()
    {
        lock (lockObj)
        {
            PQMessage messageData = null;
            PQMsgPriority deleteKey = PQMsgPriority.None;

            //If no data available, throw an exception
            if (messageDictionary.Count == 0)
                throw new InvalidOperationException();

            foreach (KeyValuePair<PQMsgPriority, Queue<PQMessage>> item in messageDictionary)
            {
                Queue<PQMessage> dataList = item.Value;
                messageData = dataList.Dequeue();
                messageDictionary[item.Key] = dataList;

                //If there is no more elements remaining in the list, set a flag (deleteKey) for deleting the key
                if (dataList.Count == 0) 
                    deleteKey = item.Key;

                break;
            }

            //If the deleteKey flag is set, delete the key from the dictionary
            if (deleteKey != PQMsgPriority.None)
                messageDictionary.Remove(deleteKey);

            return messageData;
        }
    }

    public int Count()
    {
        lock (lockObj)
        {
            return messageDictionary.Count;
        }
    }

    public PQMessage Peek()
    {
        lock (lockObj)
        {
            PQMessage messageData = null;

            //If no data available, throw an exception
            if (messageDictionary.Count == 0)
                throw new InvalidOperationException();

            foreach (KeyValuePair<PQMsgPriority, Queue<PQMessage>> item in messageDictionary)
            {
                Queue<PQMessage> dataList = item.Value;
                messageData = dataList.Peek();
                break;
            }

            return messageData;
        }
    }
}

public enum PQMsgPriority
{
    High = 0,
    Medium = 1,
    Low = 2,
    None = 3
}

public class PQMessage
{
    private PQMsgPriority msgPriority;
    private Object message;

    #region Properties
    public PQMsgPriority MsgPriority
    {
        get { return msgPriority; }
        set { msgPriority = value; }
    }
    public Object Message
    {
        get { return message; }
        set { message = value; }
    }
    #endregion

    public PQMessage(PQMsgPriority msgPriority, Object message)
    {
        this.msgPriority = msgPriority;
        this.message = message;
    }
}

如果还有其他实现优先级队列的方法,请务必指出正确的方向。

最佳答案

(我应该免责声明,我假设您这样做是为了学习而不是防弹实现。如果想要一些有用的东西,那么您最好重用现有的实现)。

只是一些一般性的评论。在下面的示例中,第三行是不必要的。

Queue<PQMessage> dataList = messageDictionary[item.MsgPriority];
dataList.Enqueue(item);
messageDictionary[item.MsgPriority] = dataList;

您从 messageDictionary 返回的 dataList 是 map 中引用的副本。这意味着当您 Enqueue 数据时,它在与以前相同的底层队列上工作(不是队列的副本),因此无需再次将其放回原处,您只需删除该行.

在您的出队实现中,您有一个循环,您每次都在第一个元素上中断(例如,您只绕过循环一次)。也许您可以研究使用 LINQ 来获取 First 元素并立即返回它? (类似于 Peek 实现`)。

最后,考虑到 PQMessage 本身有优先级,也许您可​​以考虑使用 SortedList 来实现? (参见 here)

关于c# - C#中的优先级队列实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10613186/

相关文章:

linux - 如何在 Linux 64 位机器上找出数据结构实现的内存布局

c# - 什么是 TypeAttributes.NotPublic?

c# - 命名空间未正确加载

c# - 当可以从用户对象中提取所需的属性时,像 GetPhoneNumberAsync(IdentityUser user) 这样的 UserManager 方法的目的是什么?

.net - 如何模拟类的内部方法?

c# - 在单独的窗体上刷新对象

Java - 二进制插入排序 StackOverFlowError

c# - C#中的UTF8字符串变量

c# - asp.net 文本子字符串取决于 div 的宽度

c++ - C++中的无向加权图数据结构