// <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. 苹果iphone手机上input的button按钮颜色显示有问题,安卓却没问题

    苹果手机中会如类似上图,安卓却可以按自己写的来显示 解决办法: -webkit-appearance: none; 以上即可,当然样式中可以加上通用的: 通用:input[type=button], ...

  2. mysql 主从单库单表同步 binlog-do-db replicate-do-db

    方案一:两边做主从. SELECT SUM(DATA_LENGTH)+SUM(INDEX_LENGTH) FROM information_schema.tables WHERE TABLE_SCHE ...

  3. 2014年---移动端webapp个人年度总结

    我今年是由零基础开始入门的,刚好我第一家公司入职后就马上让我接手做ipad版的专题app了.(一入门就是移动端开发,是幸运也是艰辛的开始). 我是自学前端的,当然,对Bootstrap,JQuery  ...

  4. 手持设备点击响应速度,鼠标事件与touch事件的那些事

    前言 现在一直在做移动端的开发,这次将单页应用的网页内嵌入了app,于是老大反映了一个问题:app应用点击响应慢!我开始不以为然,于是拿着网页版的试了试,好像确实有一定延迟,于是开始了研究,最后选择了 ...

  5. 记录yii2-imagine几个常用方法

    记录yii2-imagine几个常用方法: //压缩 Image::thumbnail('@webroot/img/test-image.jpg', 120, 120)->save(Yii::g ...

  6. c++ 接口和抽象类

    其实对抽象类与接口的区别一直是搞不太清楚,最近正在学习<设计模式>,期间用到了很多c++多态的知识.这是才恍然发现,是应该整理下这方面的知识了.但在翻阅书本.上网查阅资料之际,发现有篇文章 ...

  7. 如何发布带静态资源的库——android 篇

    1.首先要使用 android sdk 提供的命令行工具处理已有的项目: cd YourProjectDir android update project -p ./ 2.上一步生成的 build.x ...

  8. Linux C 收藏

    某招聘要求:熟悉高性能分布式网络服务端设计开发,熟悉epoll.多线程.异步IO.事件驱动等服务端技术: <UNIX环境高级编程(第3版)>apue.h等源码文件的编译安装 <UNI ...

  9. 通过openswan基于Azure平台搭建VPN server

    用过Azure的读者都知道,Vnet一直是Azure比较自豪的地方,尤其是VPN,Azure提供了两种VPN以及专线来保证客户数据的安全性,S2S vpn(站点到站点的,基于IPsec的),P2S v ...

  10. sublime3的安装和插件之类的

    1.http://www.sublimetext.com/3 选择适合自己电脑的下载 2.下载完之后打开,help -> enter lisence 谷了下注册码如下,粘贴过去,万一不行请自由飞 ...