java马的最小步数队列_最小优先级队列(基于最小二叉堆算法)

在最小生成树Prim算法中,可以利用最小优先级队列来改善时间复杂度,同时在单源最短路径Dijkstra算法中也同样可以利用这种最小优先级队列来改善算法时间复杂度。实现最小优先级队列可以有很多种方式,比如基于二叉最小堆,或者斐波那契堆等。这里是二叉最小堆的C#实现,原理是根据书上的伪代码来的,但有些地方我做了改进,比如书key值改变,原来书上只能变大,这里取掉了这个限制。同时还提供了根据卫星值来选择元素的功能,下面是代码:///

/// 队列元素包装类

///

/// 实际元素类型

public class QueueElement

{

///

/// Key值

///

public int KeyValue { get; internal set; }

///

/// 实际对象

///

public T Element { get; private set; }

public QueueElement(T Item, int KeyVal)

{

KeyValue = KeyVal;

Element = Item;

}

}

///

/// 最小优先级队列

///

///

public class MinHeapQueue

{

///

/// 队列元素存放,采用List实现.

///

private List> _queueValues = new List>();

///

/// 队列元素数目

///

public int Count

{

get

{

return _queueValues.Count;

}

}

///

/// 获取队列Key值最小的元素

///

///

public T GetMinimum()

{

return _queueValues[0].Element;

}

///

/// 从队列中取出Key值最小的元素

///

///

public T ExtractMin()

{

if (_queueValues.Count <= 0)

{

throw new Exception("队列为空");

}

T theMin = _queueValues[0].Element;

int theTail = Count - 1;

_queueValues[0] = _queueValues[theTail];

_queueValues.RemoveAt(theTail);

MinHeapify(0);

return theMin;

}

///

/// 整理堆元素,保持最小堆特性,这个函数跟DownAdjust功能相同

///

///

public void MinHeapify(int i)

{

int HeapSize = Count;

int theL = HeapL(i);

int theR = HeapR(i);

int theLeast = i;

if (theL < HeapSize && _queueValues[theL].KeyValue < _queueValues[theLeast].KeyValue)

{

theLeast = theL;

}

if (theR < HeapSize && _queueValues[theR].KeyValue < _queueValues[theLeast].KeyValue)

{

theLeast = theR;

}

if (theLeast != i)

{

SwapElement(i, theLeast);

MinHeapify(theLeast);

}

}

///

/// 改变元素key值

///

///

///

public void ChangeKey(Func SelectFunc, int NewKey)

{

int theIndex = -1;

for (int i = 0; i < Count; i++)

{

if (SelectFunc(_queueValues[i].Element) == true)

{

theIndex = i;

break;

}

}

if (theIndex < 0)

{

return;

}

if (_queueValues[theIndex].KeyValue < NewKey)

{

_queueValues[theIndex].KeyValue = NewKey;

DownAdjust(theIndex);

return;

}

if (_queueValues[theIndex].KeyValue > NewKey)

{

_queueValues[theIndex].KeyValue = NewKey;

UpAdjust(theIndex);

return;

}

}

///

/// 沿树根方向整理元素,保持最小堆特性

///

///

private void UpAdjust(int i)

{

int theIndex = i;

int thePIndex = HeapP(theIndex);

while (thePIndex >= 0 && _queueValues[theIndex].KeyValue < _queueValues[thePIndex].KeyValue)

{

SwapElement(thePIndex, theIndex);

theIndex = thePIndex;

thePIndex = HeapP(theIndex);

}

}

///

/// 沿树叶方向整理元素,保持最小堆特性

///

///

private void DownAdjust(int i)

{

int HeapSize = Count;

int theL = HeapL(i);

int theR = HeapR(i);

int theLeast = i;

if (theL < HeapSize && _queueValues[theL].KeyValue < _queueValues[theLeast].KeyValue)

{

theLeast = theL;

}

if (theR < HeapSize && _queueValues[theR].KeyValue < _queueValues[theLeast].KeyValue)

{

theLeast = theR;

}

if (theLeast != i)

{

SwapElement(i, theLeast);

DownAdjust(theLeast);

}

}

///

/// 改变元素key值

///

///

///

public void ChangeKey(int i, int NewKey)

{

int theIndex = i;

if (_queueValues[theIndex].KeyValue > NewKey)

{

_queueValues[theIndex].KeyValue = NewKey;

UpAdjust(theIndex);

return;

}

if (_queueValues[theIndex].KeyValue < NewKey)

{

_queueValues[theIndex].KeyValue = NewKey;

DownAdjust(theIndex);

return;

}

}

///

/// 删除队列元素

///

///

public void HeapDelete(Func SelectFunc)

{

int theIndex = -1;

for (int i = 0; i < Count; i++)

{

if (SelectFunc(_queueValues[i].Element) == true)

{

theIndex = i;

break;

}

}

if (theIndex < 0)

{

return;

}

SwapElement(theIndex, Count - 1);

_queueValues.RemoveAt(Count - 1);

if (theIndex < Count)

{

int theP = HeapP(theIndex);

bool theUp = false;

if (theP >= 0)

{

if (_queueValues[theIndex].KeyValue < _queueValues[theP].KeyValue)

{

UpAdjust(theIndex);

theUp = true;

}

}

if (theUp == false)

{

MinHeapify(theIndex);

}

}

}

///

/// 队列元素交换位置

///

///

///

private void SwapElement(int i, int j)

{

QueueElement theTmp = _queueValues[i];

_queueValues[i] = _queueValues[j];

_queueValues[j] = theTmp;

}

///

/// 将元素插入队列

///

///

///

public void HeapInsert(T Element, int Key)

{

_queueValues.Add(new QueueElement(Element, int.MinValue));

ChangeKey(Count - 1, Key);

}

///

/// 取节点的左孩子节点

///

///

///

private int HeapL(int i)

{

return i * 2 + 1;

}

///

/// 取节点的右孩子节点

///

///

///

private int HeapR(int i)

{

return i * 2 + 2;

}

///

/// 取节点的父节点

///

///

///

private int HeapP(int i)

{

return (i + 1) / 2 - 1;

}

}

需要注意的,我前面有篇基于二叉最大堆的优先级队列算法跟这篇很类似,但上篇算法中有小错误,而这篇算法中的优先级队列已通过测试,没问题。大家可对比一下,看错误在哪里。

Ps:既然到首页,还是加点注释.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值