数据结构与算法分析之堆

1.1 堆的基本概念
  • 堆的定义:堆是计算机科学中一类特殊的数据结构的统称,堆通常可以被看做是一棵完全二叉树的数组对象。
  • 堆的特性
    • 它是完全二叉树,除了树的最后一层节点不需要是满的,其他每一层从左到右都是满的,如果最后一层节点不是满的,那么要求左满右不满。
    • 它通常用数组来实现:具体方法就是将二叉树的结点按照层级顺序放入数组中,根结点在位置1,它的子系欸但在位置2和3,而子结点的子结点分别在4,5,6,7,以此类推。
      在这里插入图片描述
      在这里插入图片描述
  • 堆的构造:如果一个结点的位置未k,则它的父结点的位置未k/2,而它的两个子结点的位置为2k和2k+1。这样在不使用指针的情况下,我们也可以通过计算数组的索引在树中上下移动:从a[k]层向上一层,就令k等于k/2,向下一层就令k等于2k或2k+1.
  • 堆中的每个子结点都大于等于父结点,和二叉查找树的区别就是对于子结点的大小没有做要求。
1.2 堆的API设计

在这里插入图片描述

  • 代码实现
package com.tiger.study.DataStructure.Heap;

public class Heap<T extends Comparable<T>> {
    // 存储堆中的元素
    private T[] items;

    // 记录堆中的元素的个数
    private int N;

    public Heap(int capacity) {
        this.items = (T[]) new Comparable[capacity + 1];
        this.N = 0;
    }

    // 判断堆中索引i处的元素是否是小于索引j处的元素
    private boolean less(int i, int j) {
        return items[i].compareTo(items[j]) < 0;
    }

    // 交换堆中i索引和j索引处的值
    private void exch(int i, int j) {
        T item = items[i];
        items[i] = items[j];
        items[j] = item;
    }

    // 往堆中插入一个元素
    public void insert(T t) {
        items[++N] = t;
        swim(N);
    }

    // 使用上浮算法,使索引k处的元素能在堆中处于一个正确的位置
    private void swim(int k) {
        // 就是一直和父节点进行比较,然后如果大于父节点就交换位置
        while (k > 1) {
            // 比较当前节点和父节点
            if(!less(k, k/2)) {
                exch(k, k/2);
            }
            k = k / 2;
        }
    }

    // 删除堆中最大的元素,并返回这个最大元素
    public T delmax() {
        T max = items[1];
        // 交换索引1处的元素和最大索引处的元素,让完全二叉树中最右侧的元素变为临时根节点
        exch(1, N);

        // 最大索引处的元素删除
        items[N] = null;

        // 元素个数减1
        N--;

        // 通过下沉调整堆,让堆重新有序
        sink(1);
        return max;
    }

    // 使用下沉算法,使索引k处的元素能在堆中处于一个正确的位置
    private void sink(int k) {
        // 通过循环不断对比当前k节点和其左子节点2k和右子节点2k+1中较大的值进行比较,如果当前节点小就交换位置
        while (2*k <= N) {
            // 获取当前节点的子结点中的较大值
            int max; // 记录较大节点的索引
            if (2 * k + 1 <= N) {
                if (less(2 * k, 2*k + 1)) {
                    max = 2 * k + 1;
                } else {
                    max = 2 * k;
                }
            } else {
                max = 2 * k;
            }
            // 比较当前节点和较大节点的值
            if (!less(k, max)) {
                break;
            }
            exch(k, max);
            k = max;
        }

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值