• 二叉堆


    二叉堆即是完全二叉树实现的堆,在二叉堆中每个节点总是大于等于其任意一个子节点。根结点是二叉堆中最大的节点。

     

    数组实现二叉堆

    完全二叉树可以用数组实现,根结点的位置为1,其子节点为2、3。位置为k的节点,其两个子节点位置为2k、2k+1 。同理,位置为k的节点,其父节点的位置为k/2 。

    算法实现

    使用长度为N+1的数组key[]来表示一个大小为N的堆,不使用key[0],变量N用以记录堆的大小。

    由下至上的堆有序化(上浮)

    若某个子节点的值大于其父节点的值,可以通过交换该节点与父节点,使二叉堆有序。

    图中,节点5的键值为T大于其父节点键值P,交换后仍大于其父节点键值S,继续交换。

    上浮实现代码如下:

        private void swim(int k) {
    
            int temp;
            // k>1,k不是根结点
            // 若k节点的键值大于其父节点键值,则交换
            while (k>1 && key[k]>key[k/2]) {
                temp = key[k];
                key[k] = key[k/2];
                key[k/2] = temp;
    
                k = k/2;
            }
        }

    由上至下的堆有序化(下沉)

    若某个节点的键值小于其子节点的键值,交换该节点与其子节点可使堆保持有序

        private void sink(int k) {
    
            int temp;
            while (2*k <= N) {
    
                int j = 2*k;
                // 节点k有两个子节点:节点2k与节点2k+1
                // 选择两个子节点中键值较大的一个
                if (j < N && key[j] < key[j+1]) j++;
                if (key[j] < key[k]) break;
                temp = key[k];
                key[k] = key[j];
                key[j] = temp;
                k = j;
            }
        }

    插入元素

     将新元素添加到数组的末尾,使用上浮swim()方法将该元素上浮到合适的位置。

        public void insert(int k) {
            key[++N] = k;
            swim(N);
        }

    删除最大的元素

    二叉堆的根结点即数组的第一个元素为键值最大的元素,将数组的最后一个元素key[N]与key[1]交换,使用sink()方法,将该元素下沉到合适的位置。

        public int delMax() {
    
            int max = key[1];
            key[1] = key[N];
            key[N] = 0;
            N--;
            sink(1);
            return max;
        }

    整个程序的代码如下:

    import java.util.Arrays;
    
    public class BinaryStack {
    
        // Complete binary tree based on array
        private int[] key;
        private int N = 0;
    
        public BinaryStack(int maxN) {
    
            key = new int[maxN+1];
        }
    
        // Insert a key into the tree
        public void insert(int k) {
            key[++N] = k;
            swim(N);
        }
    
        // Delete the  maximum  key from the tree
        public int delMax() {
    
            int max = key[1];
            key[1] = key[N];
            key[N] = 0;
            N--;
            sink(1);
            return max;
        }
    
        private void swim(int k) {
    
            int temp;
            // k>1,k不是根结点
            // 若k节点的键值大于其父节点键值,则交换
            while (k>1 && key[k]>key[k/2]) {
                temp = key[k];
                key[k] = key[k/2];
                key[k/2] = temp;
    
                k = k/2;
            }
        }
    
        private void sink(int k) {
    
            int temp;
            while (2*k <= N) {
    
                int j = 2*k;
                // 节点k有两个子节点:节点2k与节点2k+1
                // 选择两个子节点中键值较大的一个
                if (j < N && key[j] < key[j+1]) j++;
                if (key[j] < key[k]) break;
                temp = key[k];
                key[k] = key[j];
                key[j] = temp;
                k = j;
            }
        }
    
    
    
        public static void main(String[] args) {
    
            BinaryStack stack = new BinaryStack(20);
            stack.insert(8);
            stack.insert(12);
            stack.insert(3);
            stack.insert(7);
            stack.insert(10);
            stack.insert(9);
            stack.insert(6);
    
            System.out.println(Arrays.toString(stack.key));
        }
    }

    算法复杂度

  • 相关阅读:
    树莓派基于scratch2控制GPIO
    一次修复linux的efi引导的集中方法总结记录
    linux(deepin) 下隐藏firefox标题栏
    log4j 1.2 配置和使用简述
    在非gnome系桌面环境下运行deepin-wine tim的错误解决
    manjaro AwesomeWM 上使用双显示器
    linux 关闭主板上的蜂鸣器声音
    anki的使用以及anki server的配置
    阅读《人类简史》-- 1.认知革命
    java生成zip包兼容Linux
  • 原文地址:https://www.cnblogs.com/deltadeblog/p/8576488.html
Copyright © 2020-2023  润新知