.net core 中实现一个堆结构
堆结构的内部是以数组实现,表现形式为一个完全二叉树,对应关系上,上级节点的下标始终等于直接下级节点的下标(任意一个)除2的除数,下级节点的坐标左孩子为上级坐标的位置x2+1,右孩子为上级坐标的位置x2+2,这个条件始终满足
如下代码就是一个简易的堆结构实现
using System;
namespace test1
{
public enum HeapType
{
Max,
Min
}
public class Heap<T> where T:IComparable<T>
{
private T[] _source;
private int _heapSize;
private HeapType _heapType;
public Heap(HeapType heapType)
{
this._heapType = heapType;
_source = new T[0];
_heapSize = 0;//堆大小为0;
}
public Heap(HeapType heapType,T[] lst)
{
this._heapType = heapType;
_source = lst;
_heapSize = lst.Length;//堆大小为0;
Heapfiy();
}
/// <summary>
/// 获取当前最前边的值
/// </summary>
public T GetTopValue
{
get
{
if (_heapSize > 0)
{
var result = _source[0];
swap(0, _heapSize-- - 1);//交换最后一个项,并调整堆大小
Heapfiy(0);
return result;
}
else
{
return default(T);
}
}
}
/// <summary>
/// 插入数据
/// </summary>
/// <param name="item"></param>
public void HeapInsert(T item)
{
if (++_heapSize > _source.Length)
{
var newlst = new T[_heapSize];
for (int i = 0; i < _source.Length; i++)
{
newlst[i] = _source[i];
}
_source = newlst;
}
_source[_heapSize-1] = item;
//与上级比较 父index= i-1/2
var currentindex = _heapSize-1;
var parrentindex = (currentindex - 1) >> 1;
while (currentindex>0)
{
switch (_heapType)
{
case HeapType.Max:
if (_source[currentindex].CompareTo(_source[parrentindex])>0)
{
swap(currentindex, parrentindex);
}
break;
case HeapType.Min:
if (_source[currentindex].CompareTo(_source[parrentindex]) < 0)
{
swap(currentindex, parrentindex);
}
break;
}
currentindex = parrentindex;
parrentindex = (currentindex - 1) >> 1;
}
}
/// <summary>
/// 某一个位置的值下移到合适的位置
/// </summary>
/// <param name="index"></param>
private void Heapfiy(int index)
{
var i = index;
switch (_heapType)
{
case HeapType.Max:
while (i * 2 + 1 < _heapSize)//有子项就一路执行,并且小于子项
{
//找到目标孩子的i
int targetchlidi = i * 2 + 1;
if (i * 2 + 2 < _heapSize)//有右孩子
{
targetchlidi = _source[i * 2 + 1].CompareTo(_source[i * 2 + 2]) > 0 ? i * 2 + 1 : i * 2 + 2;
}
if (_source[i].CompareTo(_source[targetchlidi]) < 0)
{
swap(i, targetchlidi);
i = targetchlidi;
}
else
{
break;
}
}
break;
case HeapType.Min:
while (i * 2 + 1 < _heapSize)//有子项就一路执行
{
//找到目标孩子的i
int targetchlidi = i * 2 + 1;
if (i * 2 + 2 < _heapSize)//有右孩子
{
targetchlidi = _source[i * 2 + 1].CompareTo(_source[i * 2 + 2]) < 0 ? i * 2 + 1 : i * 2 + 2;
}
if (_source[i].CompareTo(_source[targetchlidi]) > 0)
{
swap(i, targetchlidi);
i = targetchlidi;
}
else
{
break;
}
}
break;
default:
break;
}
}
/// <summary>
/// 对所有位置执行下移操作
/// </summary>
private void Heapfiy()
{
for (int i = _heapSize >> 1; i >=0; i--)
{
Heapfiy(i);
}
}
private void swap(int a, int b)
{
T r = _source[a];
_source[a] = _source[b];
_source[b] = r;
}
}
}