最小堆数据结构类实例
//最小堆
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;
        }
    }
}


主要的方法:

  1. 最小堆的创建,Create()方法,找到后数上来的第一个非叶节点,然后依次往上执行向下调整,这样就可以减少对叶节点调整的无用操作了。

  2. 向上调整,就是跟父节点对比,如果要调整,就交换位置,继续在父节点位置上对比父父节点,直到不需要调整或则到根节点为止

  3. 向下调整,同样的,不过向下调整要对比两个子节点,那么就是对比当前3个的最值,根据对比出来的值做出调整,然后继续向下调整,直到自己就是最值了或则变成叶节点了。


首页 我的博客
粤ICP备17103704号