我写的C#优先队列
2008-09-09 18:57 JimLiu 阅读(3821) 评论(10) 编辑 收藏 举报前几天才知道.NET类库里没有优先队列,而今天JAVA课上翻书时发现JAVA类库里有,不爽。本来就打算写一个的,这回正好。下午一下课就开始写,现在搞定了。
这个优先队列用二叉堆实现,泛型,需要元素实现IComparable<T>接口。
具体算法就不说了,太经典了,随便一本数据结构书都有。
堆的算法,提供了两种堆维护和一个基于堆维护的堆排序——这是一个辅助类,用于进行堆维护。
有时候用Array.Sort提供的快排腻了(还有这种人?哈哈!),玩玩堆排序也不错,常数级辅助空间,省啊!
/// <summary>
/// 大顶堆
/// </summary>
/// <typeparam name="T"></typeparam>
public class Heap<T> where T : IComparable<T> {
public static void HeapSort(T[] objects) {
for (int i = objects.Length / 2 - 1; i >= 0; --i)
heapAdjustFromTop(objects, i, objects.Length);
for (int i = objects.Length - 1; i > 0; --i) {
swap(objects, i, 0);
heapAdjustFromTop(objects, 0, i);
}
}
public static void heapAdjustFromBottom(T[] objects, int n) {
while (n > 0 && objects[(n - 1) >> 1].CompareTo(objects[n]) < 0) {
swap(objects, n, (n - 1) >> 1);
n = (n - 1) >> 1;
}
}
public static void heapAdjustFromTop(T[] objects, int n, int len) {
while ((n << 1) + 1 < len) {
int m = (n << 1) + 1;
if (m + 1 < len && objects[m].CompareTo(objects[m + 1]) < 0)
++m;
if (objects[n].CompareTo(objects[m]) > 0) return;
swap(objects, n, m);
n = m;
}
}
private static void swap(T[] objects, int a, int b) {
T tmp = objects[a];
objects[a] = objects[b];
objects[b] = tmp;
}
}
/// 大顶堆
/// </summary>
/// <typeparam name="T"></typeparam>
public class Heap<T> where T : IComparable<T> {
public static void HeapSort(T[] objects) {
for (int i = objects.Length / 2 - 1; i >= 0; --i)
heapAdjustFromTop(objects, i, objects.Length);
for (int i = objects.Length - 1; i > 0; --i) {
swap(objects, i, 0);
heapAdjustFromTop(objects, 0, i);
}
}
public static void heapAdjustFromBottom(T[] objects, int n) {
while (n > 0 && objects[(n - 1) >> 1].CompareTo(objects[n]) < 0) {
swap(objects, n, (n - 1) >> 1);
n = (n - 1) >> 1;
}
}
public static void heapAdjustFromTop(T[] objects, int n, int len) {
while ((n << 1) + 1 < len) {
int m = (n << 1) + 1;
if (m + 1 < len && objects[m].CompareTo(objects[m + 1]) < 0)
++m;
if (objects[n].CompareTo(objects[m]) > 0) return;
swap(objects, n, m);
n = m;
}
}
private static void swap(T[] objects, int a, int b) {
T tmp = objects[a];
objects[a] = objects[b];
objects[b] = tmp;
}
}
基于二叉堆的优先队列,同样需要元素实现IComparable<T>接口。
public方法我基本上按照STL里的PQ来写的,也没有任何优化(我不会)。
缓冲区满时开二倍新空间,拷贝——虽然效率不见得高,但绝对简单实用的方法。
/// <summary>
/// 泛型优先队列,大者先出队
/// </summary>
/// <typeparam name="T">实现IComparable<T>的类型</typeparam>
public class PriorityQueue<T> where T : IComparable<T> {
private const int defaultCapacity = 0x10;//默认容量为16
public PriorityQueue() {
buffer = new T[defaultCapacity];
heapLength = 0;
}
public bool Empty() {
return heapLength == 0;
}
public T Top() {
if (heapLength == 0) throw new OverflowException("优先队列为空时无法执行返回队首操作");
return buffer[0];
}
public void Push(T obj) {
if (heapLength == buffer.Length) expand();
buffer[heapLength] = obj;
Heap<T>.heapAdjustFromBottom(buffer, heapLength);
heapLength++;
}
public void Pop() {
if (heapLength == 0) throw new OverflowException("优先队列为空时无法执行出队操作");
--heapLength;
swap(0, heapLength);
Heap<T>.heapAdjustFromTop(buffer, 0, heapLength);
}
private void expand() {
Array.Resize<T>(ref buffer, buffer.Length * 2);
}
private void swap(int a, int b) {
T tmp = buffer[a];
buffer[a] = buffer[b];
buffer[b] = tmp;
}
private int heapLength;
private T[] buffer;
/// 泛型优先队列,大者先出队
/// </summary>
/// <typeparam name="T">实现IComparable<T>的类型</typeparam>
public class PriorityQueue<T> where T : IComparable<T> {
private const int defaultCapacity = 0x10;//默认容量为16
public PriorityQueue() {
buffer = new T[defaultCapacity];
heapLength = 0;
}
public bool Empty() {
return heapLength == 0;
}
public T Top() {
if (heapLength == 0) throw new OverflowException("优先队列为空时无法执行返回队首操作");
return buffer[0];
}
public void Push(T obj) {
if (heapLength == buffer.Length) expand();
buffer[heapLength] = obj;
Heap<T>.heapAdjustFromBottom(buffer, heapLength);
heapLength++;
}
public void Pop() {
if (heapLength == 0) throw new OverflowException("优先队列为空时无法执行出队操作");
--heapLength;
swap(0, heapLength);
Heap<T>.heapAdjustFromTop(buffer, 0, heapLength);
}
private void expand() {
Array.Resize<T>(ref buffer, buffer.Length * 2);
}
private void swap(int a, int b) {
T tmp = buffer[a];
buffer[a] = buffer[b];
buffer[b] = tmp;
}
private int heapLength;
private T[] buffer;
}
做了道以前的ACM题目,迷宫,优先队列BFS,原来用c++写的,46ms通过,现在这个93ms通过,出去输入输出慢,和JIT编译的时间,我觉得效率还不低——其实本来Heap可以优化的余地就不大,STL源代码大概看了下,好像也没什么优化。
虽然平衡二叉树也可以实现堆,但我总是觉得那样不爽——可能受STL影响。最重要的是——我不会写平衡二叉树,哈哈!
喜欢的、有需要的朋友就拿去用用吧,呵呵。