//最小堆
class Dui
{
public int[] datas;
public Dui() {
datas = new int[16 + 1];
}
public Dui(int maxLength) {
if (maxLength <= 0)
{
datas = new int[16 + 1];
}
else {
datas = new int[maxLength + 1];
}
}
public void ValueTo(int[] copyValues) {
datas[0] = copyValues.Length;
if (datas[0] < 1) {
return;
}
for (int i = 1; i <= datas[0]; i++) {
datas[i] = copyValues[i-1];
}
Create();//调整节点
}
public void Create() {
//倒数最后一个非叶节点
int index = datas[0] / 2;
for (int i = index; i >= 1; i--) {
SiftDown(i);
}
}
//向下调整
public void SiftDown(int index) {
bool isNeedSwap = true;
int t = index;
//有左儿子
while (index * 2 <= datas[0] && isNeedSwap) {
if (datas[index] > datas[index * 2]) {
t = index * 2;
}
//有右儿子
if (index * 2 + 1 <= datas[0]) {
if (datas[t] > datas[index * 2 + 1]) {
t = index * 2 + 1;
}
}
if (index != t)
{
int temp = datas[index];
datas[index] = datas[t];
datas[t] = temp;
index = t;
}
else {
//比左右两儿子都小了
isNeedSwap = false;
}
}
}
public void Insert(int val) {
if (datas.Length - 1 == datas[0]) {
//我这里就不重构数组了
Console.WriteLine("最小堆已满!");
return;
}
int insertIndex = datas[0] + 1;
datas[insertIndex] = val;
datas[0]++;
SiftUp(insertIndex);
}
//向上调整
public void SiftUp(int index) {
if (index == 1) return;
bool isNeedSwap = true;
int parentIndex = 0;
while (index != 1 && isNeedSwap) {
parentIndex = index / 2;
if (datas[index] < datas[parentIndex])
{
//小于父节点
int temp = datas[parentIndex];
datas[parentIndex] = datas[index];
datas[index] = temp;
}
else {
isNeedSwap = false;
}
index = parentIndex;
}
}
}主要的方法:
最小堆的创建,Create()方法,找到后数上来的第一个非叶节点,然后依次往上执行向下调整,这样就可以减少对叶节点调整的无用操作了。
向上调整,就是跟父节点对比,如果要调整,就交换位置,继续在父节点位置上对比父父节点,直到不需要调整或则到根节点为止
向下调整,同样的,不过向下调整要对比两个子节点,那么就是对比当前3个的最值,根据对比出来的值做出调整,然后继续向下调整,直到自己就是最值了或则变成叶节点了。