堆操作(2)-创建一个最大堆

一、最大堆建立

给定N个元素,按照最大堆的要求将元素放入数组中。

两种做法:

  1. 通过插入,依次将N个元素插入一个空堆中,复杂度为nlogn。
  2. 线性复杂度建立堆
    1. 先将N个元素按照顺序存入,先满足完全二叉树的特性
    2. 调整各个节点,让其满足最大堆的特性

本文主要介绍第二种方法,线性复杂度创建堆。

二、线性复杂度创建堆

默认创建一个完全二叉树

从最后一个节点的父节点【第一个父节点】(87)开始调整。87大于9。默认不变,当前子树是一个堆。

第二个父节点30。最大子节点为72。把72个30继续互换,当前子树是一个堆。

第三个父节点83。最大子节点为91。把91和83进行互换,当前子树也是一个堆。

三次交换后,树的结构如下。

从43开始调整。87大于43,互换,当前子树是一个堆。

从66开始调整,91大于66进行互换。83大于66,再次进行互换,当前子树是一个堆。

最后调整根节点;91和79互换。83和79进行互换,至此。整颗树都变成了一个堆。

代码

public static void percDown(HeapStruct heapStruct, int rootIndex) {
        Integer[] elements = heapStruct.getElements();
        Integer rootValue = elements[rootIndex];
        int parentIndex = rootIndex;
        while (parentIndex * 2 <= heapStruct.getSize() - 2) {
            int childIndex = parentIndex * 2 + 1;
            if (childIndex < heapStruct.getSize() - 1 && elements[childIndex].compareTo(elements[childIndex + 1]) < 0) {
                childIndex = childIndex + 1;//找到最大的一个儿子
            }
            if (rootValue.compareTo(elements[childIndex]) > 0) {//当前节点大于最大的儿子节点。
                break;
            } else {
                elements[parentIndex] = elements[childIndex];//和儿子节点进行替换。
                parentIndex = childIndex;
            }
        }
        elements[parentIndex]=rootValue;
    }
    @Test
    public void createHeap() {
        HeapStruct heapStruct = HeapUtil.initHeap(20);
        for (int i = 0; i < 11; i++) {
            heapStruct.getElements()[i] = i;//初始化一个数组。
        }
        for (int n = (heapStruct.getSize() - 1) / 2; n >= 0; n--) {//一个个遍历父节点,使得当前父节点所在的子树变成一个堆
            HeapUtil.percDown(heapStruct, n);
        }
    }
posted @ 2021-09-25 23:02  ibrake  阅读(1102)  评论(0编辑  收藏  举报