//最小堆 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个的最值,根据对比出来的值做出调整,然后继续向下调整,直到自己就是最值了或则变成叶节点了。