二叉树(五)堆和优先队列(heap)

1.堆的定义:堆是一颗完全二叉树,堆中存储的数据局部有序。

2.最大堆的性质:任意一个节点的值,大于等于其子节点的值,所以根据这一特性,我们知道最大堆中,根节点一定是最大的值。

3.最小堆的性质:任意一个节点的值,小于等于其子节点的值,所以根据这一特性,我们知道最小堆中,根节点一定是最小的值。

堆和BST的区别:这两者没有任何关系,BST主要是左子树一定小于右子树的节点,但是堆中,左子树的所有节点可以大于右子树的任意一个节点。可以通过排序的强度,堆只是实现了局部排序,BST实现了全局排序。

本博文采用最大堆来进行讲解。

对于建堆的过程,首先是从底层插入新的值,然后进行调整,直到符合堆的性质。这里插入一个元素的最坏情况是O(logN),插入n的元素的时间是O(NlogN).思考一下这是为什么?下面会给出答案。

建堆的java实现

package cn.edu.hust;

import java.util.ArrayList;

import static java.util.Collections.swap;

public class MaxHeap {
    private ArrayList<Integer> heap;
    //元素的个数
    private int size;

    public MaxHeap(ArrayList<Integer> heap,int size) {
        this.heap = heap;
        this.size=size;
        buildHeap();
    }

    private void buildHeap()
    {
        for (int i=size/2-1;i>=0;i--)
        {
            siftdown(i);
        }
    }

    private void siftdown(int i) {
        while(!isLeaf(i))
        {
            int leftChild=2*i+1;
            int rightChild=2*i+2;
            if((rightChild<size)&&heap.get(leftChild)<heap.get(rightChild))
            {
                leftChild=rightChild;
            }
            if(heap.get(i)>=heap.get(rightChild)) return;
            swap(heap,i,leftChild);
            i=leftChild;
        }

    }

    private boolean isLeaf(int i)
    {
        return 2*i+1>size-1;
    }

    public static void main(String[] args)
    {
        ArrayList<Integer> list=new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        list.add(6);
        list.add(7);
        MaxHeap heap=new MaxHeap(list,list.size());
        for (int i:
             list) {
            System.out.print(i+" ");
        }
    }
}

建堆的过程是,只需要从分枝节点开始,进行和子节点的比较,然后调整堆,直到符合堆的性质。具体如下图:


那么这里的建堆效率如何呢?我们知道堆的高度为logN,由于完全二叉树的性质,最底层的节点几乎是N/2,然后是N/4,所以移动的步数是:


如果删除最大的一个值,会发生什么事情呢?

那么我们需要重新调节堆,这里可以利用上述的sfitdwon函数进行调整。调整的时间复杂度为O(logN),插入也是类似的原理。




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值