二叉堆的理解和操作

堆的概念:
    如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储
    方式存储在一个一维数组中,并满足:Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) 
    i = 0,1,2…,则称为小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆
    叫做最小堆或小根堆。
堆的性质:
    堆中某个节点的值总是不大于或不小于其父节点的值;
    堆总是一棵完全二叉树。

堆是弱序的,但二叉堆总是一个完全二叉树,可以用一个一维数组层序遍历存储二叉堆的值,这样就可以把一个弱序的二叉堆转化成一个有序的一维数组。这样就能够以O(1)的时间复杂度快速查找到堆的最大元素(大堆)或最小元素(小堆)。

堆中结点与其对应数组下标关系:
传入数组下标index(对应二叉树中的某个结点n所对应的数组下标),有效长度size(二叉树中的结点个数);
n的左孩子下标:2*index+1;
n的右孩子下标:2*index+2;
n的双亲下标:(index-1)/2;
判断n是否为叶子结点: 2*index+1>=size  ->为叶子节点
根节点:index=0;
层序遍历的最后一个节点:index=size-1;
下面是关于二叉堆的一些基本操作:
交换数组中两个元素的位置
private  void swap(long[]array,int i,int j){
        long temp=array[i];
        array[i]=array[j];
        array[j]=temp;
    }
下面以小堆的操作为例:
向下调整(下沉) 时间复杂度O(log n)

将要调整的结点与其左右孩子作比较,不断交换结点位置,直到二叉堆满足小堆的性质

   public void adjustdown(long[]array,int size,int index){
        while(2*index+1<size){
            int minindex=2*index+1;
            if (minindex+1<size&&array[minindex+1]<array[minindex]){
                minindex++;
            }
            if (array[index]<=array[minindex]){return;}
            swap(array,index,minindex);
            index=minindex;
        }
    }
向上调整(上浮) 时间复杂度O(log n)

将要调整的结点与双亲作比较,不断交换结点位置,直到二叉堆满足小堆的性质

    public void adjustup(long[]array,int index){
        while(index!=0){
            int pindex=(index-1)/2;
            if (array[pindex]<=array[index]){
                return;
            }
            swap(array,pindex,index);
            index=pindex;
        }
    }
建堆 时间复杂度O(n)

从层序遍历的最后一个结点的双亲开始一直向前到根结点,不断做向下调整

  public  void createsmallHeap(long[]array,int size){
        //最后一个元素的双亲的下标
        int pindex=(size-2)/2;
        for (int i = pindex; i >=0; i--) {
            adjustdown(array,size,i);
        }
    }
关于大堆的一些基础操作(与小堆类似)
 //(大堆)向下调整(下沉)(非递归)
    //时间复杂度O(log n)
    public  void adjustdownlarge(long[]array,int size,int index){
        while(2*index+1<size){
            int maxindex=2*index+1;
            if (maxindex+1<size&&array[maxindex+1]>array[maxindex]){
                maxindex++;
            }
            if (array[index]>=array[maxindex]){return;}
            swap(array,index,maxindex);
            index=maxindex;
        }
    }
    //(大堆)向上调整(上浮)(非递归)
    //时间复杂度O(log n)
    public  void adjustuplarge(long[]array,int index){
        while(index!=0){
            int pindex=(index-1)/2;
            if (array[pindex]>=array[index]){
                return;
            }
            swap(array,pindex,index);
            index=pindex;
        }
    }
    //(大堆)建堆
    //时间复杂度O(n)
    public  void createlargeHeap(long[]array,int size){
        //最后一个元素的双亲的下标
        int pindex=(size-2)/2;
        for (int i = pindex; i >=0; i--) {
            adjustdownlarge(array,size,i);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值