用java实现堆

1、堆是一种特殊的二叉树

堆总是一颗完全二叉树(即除最底层外,其它层节点都被元素填满,且最底层从左向右尽可能填满结点)

2、分为最大堆和最小堆,最大堆中某结点的值总是不大于其父节点的值,最小堆中某结点的值总是不小于其父节点的值

3、堆的实现:  用数组实现    构造二叉树     

ArrayList<Integer> array=new ArrayList<Integer>();
//ArrayList<Integer> array=new ArrayList<Integer>(capacity);

数组是按层次存放堆这棵二叉树中的结点值的

数组中的元素并不是按从大到小的顺序排列的,从堆中取出元素只能取出堆顶元素,即只能获得最大值或最小值

4、index为数组中当前元素的索引,则该元素的父节点在数组中的索引为(index-1)/2,该元素的左孩子在数组中的索引为2*index+1,该元素的右孩子在数组中的索引为2*index+2

5、以最大堆为例

(1)向堆中添加元素:

时间复杂度:O(logn)

将该元素先添加到数组的尾部(即充当最底层的最后一个叶结点),然后将该元素与其父节点进行大小比较,若大于其父节点则与父节点进行交换,继续与上一层父节点进行比较,如此重复,直至小于等于父节点为止

    //向堆中添加元素
    public void addValue(ArrayList<Integer> array,int value)
    {
        if(array==null)
            return;
        array.add(value);
        int i=array.size()-1;
        while(i>=1&&value>array.get((i-1)/2))
        {
            array.set(i,array.get((i-1)/2));
            array.set((i-1)/2,value);
            i=(i-1)/2;
        }
    }

(2)删除堆元素:

时间复杂度:O(logn)

将堆顶元素A与最后一个元素B交换后(即数组的首尾元素互换),删除A,从堆顶元素开始比较其与左右孩子的大小,若同时小于左右孩子,则与左右孩子中的较大者交换,否则与大于其的孩子交换,继续与下一层左右孩子进行比较,如此重复,直至大于等于左右孩子为止

removeValue=swap+sift

    //删除堆顶元素
    public void removeValue(ArrayList<Integer> array)
    {
        if(array==null||array.size()==0)
            return;
        array.set(0,array.get(array.size()-1));
        array.remove(array.size()-1);
        int i=0;
        while(2*i+1<array.size())
        {
            int value=array.get(i);
            int a=array.get(2*i+1);
            int max=a;
            int index=2*i+1;
            //左右孩子都存在
            if(2*i+2<array.size())
            {
                int b=array.get(2*i+2);
                if(b>a)
                {
                    max=b;
                    index=2*i+2;
                }
            }
            if(value<max)
            {
                array.set(i,max);
                array.set(index,value);
                i=index;
            }
            else
                break;
        }
    }

(3)返回堆中的元素个数

return array.size();

(4)判断堆是否为空

return array.isEmpty();

(5)返回数组索引

//返回父节点在数组中的索引
return (index-1)/2;
//返回左孩子在数组中的索引
return 2*index+1;
//返回右孩子在数组中的索引
return 2*index+2;

(6)替换:将堆顶元素替换为其他元素

         时间复杂度:O(logn)

removeValue()+addValue()

(7)Heapify:将任意数组转化为堆的形状

时间复杂度:O(n)

将数组看成一棵完全二叉树,从最后一个叶节点的父节点开始,到根节点结束,依次判断各节点与其左右孩子的大小关系并进行调整

0~array.size()-1/2进行sift

public void heapify(ArrayList<Integer> array)
{
    int y=array.size()-1;
    int i=(y-1)/2;
    for(int j=i;j>=0;j--)
        sift(array,j);
    return;
}
public void sift(ArrayList<Integer> array,int i)
{
    while(2*i+1<array.size())
    {
       int value=array.get(i);
       int a=array.get(2*i+1);
       int max=a;
       int index=2*i+1;
       //左右孩子都存在
       if(2*i+2<array.size())
       {
          int b=array.get(2*i+2);
          if(b>a)
          {
             max=b;
             index=2*i+2;
          }
       }
       if(value<max)
       {
          array.set(i,max);
          array.set(index,value);
          i=index;
       }
       else
          break;
    }
}


将n个元素插入一个空堆中,时间复杂度为O(nlogn)

6、优先队列具有最高优先级先出的特点,所以采用最大堆数据结构

      java.util.PriorityQueue类底层就是通过优先级堆实现的

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值