// <copyright file="KeyedPriorityQueue.cs" company="Microsoft">Copyright (c) Microsoft Corporation.  All rights reserved.</copyright>
namespace Microshaoft
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
//internal sealed class KeyedPriorityQueueHeadChangedEventArgs<T> : EventArgs where T : class
//{
// private T oldFirstElement;
// private T newFirstElement;
// public KeyedPriorityQueueHeadChangedEventArgs(T oldFirstElement, T newFirstElement)
// {
// this.oldFirstElement = oldFirstElement;
// this.newFirstElement = newFirstElement;
// }
// public T OldFirstElement { get { return oldFirstElement; } }
// public T NewFirstElement { get { return newFirstElement; } }
//}
///// <summary> Combines the functionality of a dictionary and a heap-sorted priority queue.
///// Enqueue and Dequeue operations are O(log n), Peek is O(1) and Remove is O(n).
///// Used by the SchedulerService classes to maintain an ordered list of running timers, etc.
///// Lesser priority values are higher priority.</summary>
///// <typeparam name="K">Key</typeparam>
///// <typeparam name="V">Value</typeparam>
///// <typeparam name="P">Priority</typeparam>
[Serializable]
public class KeyedPriorityQueue<TKey, TValue, TPriority>
where TValue : class
{
//private ConcurrentBag<HeapNode<TKey, TValue, TPriority>> _heap = new ConcurrentBag<HeapNode<TKey, TValue, TPriority>>();
private List<HeapNode<TKey, TValue, TPriority>> _heap = new List<HeapNode<TKey, TValue, TPriority>>();
private int _size;
private Comparer<TPriority> _priorityComparer = Comparer<TPriority>.Default;
private HeapNode<TKey, TValue, TPriority> _placeHolder = default(HeapNode<TKey, TValue, TPriority>);
//public event EventHandler<KeyedPriorityQueueHeadChangedEventArgs<V>> FirstElementChanged;
private Action<TValue, TValue> _onKeyedPriorityQueueHeadChangedProcessAction = null;
private Func<HeapNode<TKey, TValue, TPriority>, HeapNode<TKey, TValue, TPriority>, bool> _onPriorityComparerProcessFunction = null;
public KeyedPriorityQueue
(
Action<TValue, TValue> onKeyedPriorityQueueHeadChangedProcessAction = null
, Func<HeapNode<TKey, TValue, TPriority>, HeapNode<TKey, TValue, TPriority>, bool> onPriorityComparerProcessFunction = null
)
{
_onKeyedPriorityQueueHeadChangedProcessAction = onKeyedPriorityQueueHeadChangedProcessAction;
_onPriorityComparerProcessFunction = onPriorityComparerProcessFunction;
_heap.Add(default(HeapNode<TKey, TValue, TPriority>)); // Dummy zeroth element, heap is 1-based
}
public void Enqueue
(
TKey key
, TValue value
, TPriority priority
)
{
TValue oldHead = _size > 0 ? _heap[1].Value : null;
int i = ++_size;
int parent = i / 2;
if (i == _heap.Count)
{
_heap.Add(_placeHolder);
}
var heapNode = new HeapNode<TKey, TValue, TPriority>(key, value, priority);
bool isHigher = IsHigher(heapNode, _heap[parent]);
while (i > 1 && isHigher)
{
_heap[i] = _heap[parent];
i = parent;
parent = i / 2;
}
_heap[i] = heapNode;
TValue newHead = _heap[1].Value;
if (!newHead.Equals(oldHead))
{
RaiseHeadChangedEvent(oldHead, newHead);
}
}
public TValue Dequeue()
{
TValue oldHead = (_size < 1) ? null : DequeueImpl();
TValue newHead = (_size < 1) ? null : _heap[1].Value;
RaiseHeadChangedEvent(null, newHead);
return oldHead;
}
private TValue DequeueImpl()
{
Debug.Assert(_size > 0, "Queue Underflow");
TValue oldHead = _heap[1].Value;
_heap[1] = _heap[_size];
_heap[_size--] = _placeHolder;
Heapify(1);
return oldHead;
}
public TValue Remove(TKey key)
{
if (_size < 1)
{
return null;
}
TValue oldHead = _heap[1].Value;
for (int i = 1; i <= _size; i++)
{
if (_heap[i].Key.Equals(key))
{
TValue retval = _heap[i].Value;
Swap(i, _size);
_heap[_size--] = _placeHolder;
Heapify(i);
TValue newHead = _heap[1].Value;
if (!oldHead.Equals(newHead))
{
RaiseHeadChangedEvent(oldHead, newHead);
}
return retval;
}
}
return null;
}
public TValue Peek()
{
return (_size < 1) ? null : _heap[1].Value;
}
public int Count
{
get
{
return _size;
}
}
public TValue FindByPriority(TPriority priority, Predicate<TValue> match)
{
return _size < 1 ? null : Search(priority, 1, match);
}
public ReadOnlyCollection<TValue> Values
{
get
{
List<TValue> values = new List<TValue>();
for (int i = 1; i <= _size; i++)
{
values.Add(_heap[i].Value);
}
return new ReadOnlyCollection<TValue>(values);
}
}
public ReadOnlyCollection<TKey> Keys
{
get
{
List<TKey> keys = new List<TKey>();
for (int i = 1; i <= _size; i++)
{
keys.Add(_heap[i].Key);
}
return new ReadOnlyCollection<TKey>(keys);
}
}
public void Clear()
{
_heap.Clear();
_size = 0;
}
private void RaiseHeadChangedEvent(TValue oldHead, TValue newHead)
{
if (oldHead != newHead)
{
//EventHandler<KeyedPriorityQueueHeadChangedEventArgs<V>> fec = FirstElementChanged;
if (_onKeyedPriorityQueueHeadChangedProcessAction != null)
{
_onKeyedPriorityQueueHeadChangedProcessAction(oldHead, newHead);
}
}
}
private TValue Search(TPriority priority, int i, Predicate<TValue> match)
{
Debug.Assert(i >= 1 || i <= _size, "Index out of range: i = " + i + ", size = " + _size);
TValue value = null;
var isHigher = IsHigher(_heap[i], priority);
if (isHigher)
{
if (match(_heap[i].Value))
{
value = _heap[i].Value;
}
int left = 2 * i;
int right = left + 1;
if (value == null && left <= _size)
{
value = Search(priority, left, match);
}
if (value == null && right <= _size)
{
value = Search(priority, right, match);
}
}
return value;
}
private void Heapify(int i)
{
Debug.Assert(i >= 1 || i <= _size, "Index out of range: i = " + i + ", size = " + _size);
int left = 2 * i;
int right = left + 1;
int highest = i;
if (left <= _size && IsHigher(_heap[left], _heap[i]))
{
highest = left;
}
if (right <= _size && IsHigher(_heap[right], _heap[highest]))
{
highest = right;
}
if (highest != i)
{
Swap(i, highest);
Heapify(highest);
}
}
private void Swap(int i, int j)
{
Debug.Assert(i >= 1 || j >= 1 || i <= _size || j <= _size, "Index out of range: i = " + i + ", j = " + j + ", size = " + _size);
HeapNode<TKey, TValue, TPriority> temp = _heap[i];
_heap[i] = _heap[j];
_heap[j] = temp;
}
private bool IsHigher
(
HeapNode<TKey, TValue, TPriority> compare
, TPriority compareWithPriority
)
{
var r = false;
if (_onPriorityComparerProcessFunction != null)
{
var compareWithHeapNode
= new HeapNode<TKey, TValue, TPriority>
(default(TKey), default(TValue), compareWithPriority);
r = _onPriorityComparerProcessFunction(compare, compareWithHeapNode);
}
else
{
r = _priorityComparer.Compare(compare.Priority, compareWithPriority) < 1;
}
return r;
}
private bool IsHigher
(
HeapNode<TKey, TValue, TPriority> compare
, HeapNode<TKey, TValue, TPriority> compareWith
)
{
var r = false;
if (_onPriorityComparerProcessFunction != null)
{
r = _onPriorityComparerProcessFunction(compare, compareWith);
}
else
{
r = _priorityComparer.Compare(compare.Priority, compareWith.Priority) < 1;
}
return r;
}
[Serializable]
public struct HeapNode<KeyT, ValueT, PriorityT>
{
public KeyT Key;
public ValueT Value;
public PriorityT Priority;
public HeapNode(KeyT key, ValueT value, PriorityT priority)
{
Key = key;
Value = value;
Priority = priority;
}
}
}
}

KeyedPriorityQueue的更多相关文章

  1. WWF3.5SP1 参考源码索引

    http://www.projky.com/dotnet/WF3.5SP1/System/Runtime/Serialization/FormatterServicesNoSerializableCh ...

随机推荐

  1. [Unreal]学习笔记之材质说明

    取消蓝图中的连接线:Alt+鼠标左键 在蓝图中,通过按住1,2,3,4加鼠标左键,可以快速生成1,2,3,4维的向量 材质和材质实例的区别:使用一个母材质,可以创建出多种场景中的材质实例:每次修改母材 ...

  2. ASP.NET MVC移动M站建设-使用51Degree 移动设备的识别

    上一篇,介绍了移动M站的建设.说的很简单.觉得好像也没把M站给讲清楚.估计是对移动M站 认识还不够深刻吧.这里,在讲一讲51Degree 这个组件. 51degrees 号称是目前最快.最准确的设备检 ...

  3. 记录分享公司Spring data相关配置

    起因 公司Spring Data相关的配置还是有点意思的,不过蛮复杂的...XML很多...我不太喜欢强行记住....所以我打算记录一下配置的大致思路和结构,以后可能会有用.... 总体结构 总体结构 ...

  4. 【转载学习前辈的经验】-- Mistakes I made (as a developer) 我(作为一名开发者)所犯过的错误

    我 2006 年开始工作,至今已经 10 年.10 年是个里程碑,我开始回顾自己曾经犯过的错误,以及我希望从同行那里得到什么类型的忠告.一切都在快速改变,10 年了,我不能确定这些秘诀是否还有用. 不 ...

  5. 解决Maven工程中报 Missing artifact jdk.tools:jdk.tools:

    jdk.tools:jdk.tools是与JDK一起分发的一个JAR文件,可以如下方式加入到Maven项目中:<dependency>    <groupId>jdk.tool ...

  6. asp.net core输出中文乱码的问题

    摘要 在学习asp.net core的时候,尝试在控制台,或者页面上输出中文,会出现乱码的问题. 问题重现 新建控制台和站点 public class Program { public static ...

  7. velocity中$springMacroRequestContext.getMessage($code)

    在Java国际化(i18n)中, vm页面显示内容需要使用 #springMessage("title") 实际运行时发现页面输出$springMacroRequestContex ...

  8. vtkQuadratic创建半球面

    用的关键类:vtkQuadric.vtkSampleFunction.vtkContourFilter:用于创建方框的类vtkOutlineFilter #ifndef INITIAL_OPENGL ...

  9. iOS多线程-RunLoop简介

    什么是RunLoop? 从字面上来看是运行循环的意思. 内部就是一个do{}while循环,在这个循环里内部不断的处理各种任务(比如:source/timer/Observer) RunLoop的存在 ...

  10. python --> 正则表达式

    在python中使用正则表达式,需要导入 re 模块 一. 元字符,包括 []  {} | ? * +  .  ^ $ \  () . 号:通配符,一个点号就代表一个字符,一般情况下不能通配换行符 \ ...