0
点赞
收藏
分享

微信扫一扫

算法基础入门 - 6、复杂排序算法-堆结构介绍及示例

河南妞 2022-04-03 阅读 89

堆结构

堆结构就是用数组实现的完全二叉树结构(有右子节点时,必有左子节点)

堆的类型有两种:

堆中的方法:

堆结构优点(以下解释以大根堆为例):

下面用代码示例来演示堆结构

package com.leftGod;

/**
 * 基础堆结构
 *
 * 基础:
 * 求父节点下标:(i-1)/2
 * 求左孩子节点下标:i*2+1
 * 求右孩子节点下标:i*2+2
 *
 * @author zhao.hualuo
 * Create at 2022/4/2
 */
public class BaseHeap {

    /** 堆当前使用量 */
    private static int heapSize = 0;

    /** 堆数组,用来存放当前元素 */
    private static int[] heapArr = new int[4];

    /**
     * heapInsert
     *
     * @param newValue 要插入到堆中的新值
     */
    public static void heapInsert(int newValue) {
        //1、将这个新元素放到堆的最后一个位置,堆的长度+1
        heapArr[heapSize] = newValue;

        //1、将现在的数组重新转化成堆
        int index = heapSize;
        while (index>=0 && heapArr[index] > heapArr[(index-1)/2]) {
            swap(index, (index-1)/2);
            index = (index-1)/2;
        }

        //堆长度+1
        heapSize++;
        //判断堆是否需要扩容
        expansion();
    }

    /**
     * heapify
     * 代码中注释1和注释2只会有一个成立
     *
     * @param index 要移除的元素下标
     * @return 移除的元素值
     */
    public static int heapify(int index) {
        int returnValue = heapArr[index];

        //将最后一个位置的元素交换到要移除的这个元素位置上
        swap(index, heapSize-1);

        //1、看看这个元素是不是比父元素要大。若是,需要上移
        while (index>=0 && heapArr[index] > heapArr[(index-1)/2]) {
            swap(index, (index-1)/2);
            index = (index-1)/2;
        }

        //2、看看这个元素是不是比子元素要小。若是,需要下沉
        int left = index*2+1;
        while (left < heapSize) {
            //看看两个子元素那个大,下一步要和大的进行比较替换
            int maxSonIndex = left+1<heapSize && heapArr[left+1] >heapArr[left] ? left+1 : left;
            //当前元素和较大的那个儿子作比较,若父亲比两个儿子都大,匹配成功,循环结束
            if (heapArr[index] >= heapArr[maxSonIndex]) {
                break;
            }
            //走到这一步,说明儿子比老子大,老子和儿子要交换位置
            swap(index, maxSonIndex);
            //准备下一次循环
            index = maxSonIndex;
            left = left*2+1;
        }
        heapSize--;
        return returnValue;
    }

    /**
     * 堆自动扩容机制
     */
    private static void expansion() {
        //判断是否需要扩容
        if (heapSize < heapArr.length) {
            return;
        }
        //创建新数组,并复制
        int[] newHeapArr = new int[heapArr.length*2];
        System.arraycopy(heapArr, 0, newHeapArr, 0, heapArr.length);
        heapArr = newHeapArr;
        System.out.println("触发扩容,新堆长度:" + heapArr.length);
    }

    /**
     * 将两个元素交换位置
     *
     * @param originIndex 原位置
     * @param targetIndex 目标位置
     */
    private static void swap(int originIndex, int targetIndex) {
        if (originIndex == targetIndex) {
            return;
        }
        heapArr[originIndex] = heapArr[originIndex] ^ heapArr[targetIndex];
        heapArr[targetIndex] = heapArr[originIndex] ^ heapArr[targetIndex];
        heapArr[originIndex] = heapArr[originIndex] ^ heapArr[targetIndex];
    }

    public static void main(String[] args) {
        //测试heapInsert
        heapInsert(15);
        heapInsert(40);
        heapInsert(9);
        heapInsert(8);
        heapInsert(32);
        heapInsert(39);
        heapInsert(35);
        System.out.println("\n当前堆大小:" + heapArr.length + ",已占用堆空间:" + heapSize);
        System.out.print("heapInsert结果:");
        for (int i = 0; i < heapSize; i++) {
            System.out.print(heapArr[i] + ", ");
        }
        System.out.println();
        //[40, 32, 39, 8, 15, 9, 35, 0]

        //测试heapify
        //应该将8删除,用最后一个元素35来替换,35会和父亲32做一次heapInsert
        heapify(3);
        System.out.println("\n当前堆大小:" + heapArr.length + ",已占用堆空间:" + heapSize);
        System.out.print("heapify结果:");
        for (int i = 0; i < heapSize; i++) {
            System.out.print(heapArr[i] + ", ");
        }
        //[40, 35, 39, 32, 15, 9, 8, 0]
    }
}

上面示例的运行结果如下:

"C:\Program Files\Java\jdk1.8.0_212\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.2.2\lib\idea_rt.jar=9226:C:\Program Files\JetBrains\IntelliJ IDEA 2019.2.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_212\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_212\jre\lib\rt.jar;D:\CodeWorkspace\PersonCode\demo\target\classes;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter\2.4.3\spring-boot-starter-2.4.3.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot\2.4.3\spring-boot-2.4.3.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-context\5.3.4\spring-context-5.3.4.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-aop\5.3.4\spring-aop-5.3.4.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-beans\5.3.4\spring-beans-5.3.4.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-expression\5.3.4\spring-expression-5.3.4.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.4.3\spring-boot-autoconfigure-2.4.3.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.4.3\spring-boot-starter-logging-2.4.3.jar;C:\Users\Administrator\.m2\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;C:\Users\Administrator\.m2\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;C:\Users\Administrator\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.13.3\log4j-to-slf4j-2.13.3.jar;C:\Users\Administrator\.m2\repository\org\apache\logging\log4j\log4j-api\2.13.3\log4j-api-2.13.3.jar;C:\Users\Administrator\.m2\repository\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;C:\Users\Administrator\.m2\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-core\5.3.4\spring-core-5.3.4.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-jcl\5.3.4\spring-jcl-5.3.4.jar;C:\Users\Administrator\.m2\repository\org\yaml\snakeyaml\1.27\snakeyaml-1.27.jar;C:\Users\Administrator\.m2\repository\com\gexin\platform\gexin-rp-sdk-http\4.1.0.5\gexin-rp-sdk-http-4.1.0.5.jar;C:\Users\Administrator\.m2\repository\com\gexin\platform\gexin-rp-sdk-template\4.0.0.24\gexin-rp-sdk-template-4.0.0.24.jar;C:\Users\Administrator\.m2\repository\com\gexin\platform\gexin-rp-sdk-base\4.0.0.30\gexin-rp-sdk-base-4.0.0.30.jar;C:\Users\Administrator\.m2\repository\com\google\protobuf\protobuf-java\2.5.0\protobuf-java-2.5.0.jar;C:\Users\Administrator\.m2\repository\com\gexin\platform\gexin-rp-fastjson\1.0.0.3\gexin-rp-fastjson-1.0.0.3.jar;C:\Users\Administrator\.m2\repository\com\getui\push\restful-sdk\1.0.0.1\restful-sdk-1.0.0.1.jar;C:\Users\Administrator\.m2\repository\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;C:\Users\Administrator\.m2\repository\org\apache\httpcomponents\httpclient\4.5.13\httpclient-4.5.13.jar;C:\Users\Administrator\.m2\repository\org\apache\httpcomponents\httpcore\4.4.14\httpcore-4.4.14.jar;C:\Users\Administrator\.m2\repository\commons-codec\commons-codec\1.15\commons-codec-1.15.jar;C:\Users\Administrator\.m2\repository\com\google\code\gson\gson\2.8.6\gson-2.8.6.jar" com.leftGod.BaseHeap
触发扩容,新堆长度:8

当前堆大小:8,已占用堆空间:7
heapInsert结果:40, 32, 39, 8, 15, 9, 35, 

当前堆大小:8,已占用堆空间:6
heapify结果:40, 35, 39, 32, 15, 9, 
Process finished with exit code 0
举报

相关推荐

算法入门基础:排序算法

0 条评论