【数据结构】——堆

1.堆的介绍:

(1)堆逻辑上是一棵完全二叉树;

(2)堆物理上是保存在数组中;

(3)满足任意节点的值都大于其子树中节点的值——大根堆,大堆 或者最大堆

(4) 相反,则是小根堆,小堆,或者最小堆。

2.根据数组序列创建小根堆过程分析:

分析:

(1)index(代表要调整位置的下标) 如果已经是叶子节点,则整个调整过程结束;

  •  判断index 位置是否有孩子节点;
  • 只对其判断是否有左孩子;因为堆是完全二叉树,即没有左孩子就一定没有右孩子;
  • 判断是否有左孩子即判断左孩子下标是否越界,即left  >= size(数组长度)越界;

(2)确定index 节点的左右孩子的最小值min;

  • 若右孩子不存在;则 min = left;
  • 否则,比较array[left]  和array[right]的值,选择小的为min;

(3)比较array[index]   的值 和 array[min]   的值,如果 array[index] <= array[min];z则满足小堆的性质,调整结束;

(4)否则,交换array[index]  和 array[min]  的值;

(5)因min位置可能破坏了堆的性质,将min看做index向下重复此过程;

3.数组序列创建大根堆的实现:

public class HeapTest {
    public int[] elem;
    public int usedSize;

    public HeapTest() {
        this.elem = new int[10];
    }

    //1)创建大根堆
    public  void createBigHeap(int[] array){
        for(int i = 0;i < array.length;i++){
            this.elem[i] = array[i];
            this.usedSize ++;
        }
        //此时elem[]中已经存放了元素
        for(int i = (this.usedSize - 1 - 1 )/2;i >= 0;i--){
            adjustDown(i,usedSize);
        }
    }
    //2)向下调整
    public  void adjustDown(int parent,int len){
        int child = 2 * parent + 1;
        while(child < len){
            //child + 1 < len  判断当前是否  有右孩子
            if(child + 1 < len &&  this.elem[child] < this.elem[child + 1]){
                child++;
            }
            //此时child 下标 一定是 左右孩子的最大值下标
            if(this.elem[parent] < this.elem[child]){
                int tmp = this.elem[parent];
                this.elem[parent] = this.elem[child];
                this.elem[child] = tmp;
                parent = child;
                child = 2 * parent + 1;
            }else{
                //因为是从最后一棵树开始调整的,
                // 当this.elem[parent] > this.elem[child]
                //后续就不需要循环了,后面的都已经是大根堆了
                break;
            }
        }
    }

    public void show(){
        for (int i = 0; i <this.usedSize; i++) {
            System.out.print(this.elem[i] + " ");
        }
        System.out.println();
    }
}

运行结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值