算法基础之--最大堆实现

这里写图片描述
上图红色代表树节点索引;

左子节点和父节点的索引关系是 : 2*n
右子节点和父节点的索引关系是 : 2*n +1

package demo;
/**
 * 
 * @author Administrator
 * 最大树----------------------------------------
 */
public class MaxHeap {
    //定义这个堆最大能存多少个元素
    public static int[] data;
    //记录当前索引位置,因为图中是第一个元素不是0,而是从1开始记录的
    public static int count;

    private static int size;
    //默认构造初始化堆空间大小
    protected MaxHeap (int size) {      
        this.data = new int[size+1];
        count = 0;
        this.size = size;
    }

    protected int size(){return count; };
    //向堆中添加元素
    public static void insert(int item){
        assert count + 1 <= size;
        //将当前元素存入到堆结构中,因为从下表从一开始的所以,记录索引的值得+1
        data[count+1] = item;
        //更新记录值
        count ++;
        //到目前为止我们只是添加了一个元素,为了满足最大堆的特点即父节点大于两个子节点所以得对当前新添加的元素
        //从新更新为止,直到符合最大堆得要求
        shiftUp(count);
    }
    /**
     * 取出最大元素的规则如下:
     * 1,将当前堆中最大的元素,也就是第一个结点,与最后一个节点交换值;
     * 2,记录索引的count进行自减一,相当于剔除交换后整个堆得最后一个元素,也就是之前的第一个元素
     * 3,最后判断这个新的头节点,也就是第一个元素是否满足最大推得特点。
     */
    public void  extractMax(){
        //获取第一个元素
        int returns = data[1];  
        //将头节点与最后一个节点进行交换
        switchs(count,1);
        count--; //忽略最后一个元素
        //对新的头节点进行交换,直至满足最大堆得条件
        shiftDown(1);   
        System.out.print(returns);
    };

    static void shiftUp(int k){
        //当前传入节点的索引即为新加元素的节点,父节点索引即为 k/2,如果子节点大于父节点,进行交换
        while( k > 1 && data[k] > data[k/2]){
            //置换两个节点的值
            switchs(k,k/2);
            //更新k的值,继续循环,直到所有的数据都满足条件
            k =k/2;
        }
    }

    static void shiftDown(int l){       
        //判断当前节点是否有左节点,有的话执行
        while(2*l <= count){
            int itrmchange = 2*l; 
            //itrmchange +1 也就是右节点是否存在,并且如果右节点大于左节点的值,那么头节点跟父节点进行置换
            //否则与左节点置换
            if(itrmchange +1 <= count && data[itrmchange+1]>data[itrmchange])
                itrmchange=itrmchange+1;
            //继续判断头结点是否大于子节点,满足跳出循环
            if(data[l] >= data[itrmchange])
                break;
            //否则继续交换值
            switchs(l, itrmchange);
            //更新节点
            l=itrmchange;               
        }

    }
    //交换两个节点值
    static void switchs(int i,int j){
        int t = data[i];
        data[i] =data[j];
        data[j] = t;        
    };

}

工具测试类:

package bobo.algo;

import demo.MaxHeap;

// 我们的PrintableMaxHeap只能处理整数信息,所以继承的是MaxHeap<Comparable<Integer>>
public class PrintableMaxHeap extends MaxHeap{

    public PrintableMaxHeap(int capacity){
        super(capacity);
    }

    // 以树状打印整个堆结构
    public void treePrint(){

        if( size() >= 100 ){
            System.out.println("This print function can only work for less than 100 integer");
            return;
        }

        System.out.println("The max heap size is: " + size());
        System.out.println("Data in the max heap: ");
        for( int i = 1 ; i <= size() ; i ++ ){
            // 我们的print函数要求堆中的所有整数在[0, 100)的范围内
            assert (Integer)data[i] >= 0 && (Integer)data[i] < 100;
            System.out.print(data[i] + " ");
        }
        System.out.println();
        System.out.println();

        int n = size();
        int maxLevel = 0;
        int numberPerLevel = 1;
        while( n > 0 ){
            maxLevel += 1;
            n -= numberPerLevel;
            numberPerLevel *= 2;
        }

        int maxLevelNumber = (int)Math.pow(2, maxLevel-1);
        int curTreeMaxLevelNumber = maxLevelNumber;
        int index = 1;
        for( int level = 0 ; level < maxLevel ; level ++ ){

            String line1 = new String(new char[maxLevelNumber*3-1]).replace('\0', ' ');

            int curLevelNumber = Math.min(count-(int)Math.pow(2,level)+1,(int)Math.pow(2,level));
            boolean isLeft = true;
            for( int indexCurLevel = 0 ; indexCurLevel < curLevelNumber ; index ++ , indexCurLevel ++ ){
                line1 = putNumberInLine( (Integer)data[index] , line1 , indexCurLevel , curTreeMaxLevelNumber*3-1 , isLeft );
                isLeft = !isLeft;
            }
            System.out.println(line1);

            if( level == maxLevel - 1 )
                break;

            String line2 = new String(new char[maxLevelNumber*3-1]).replace('\0', ' ');
            for( int indexCurLevel = 0 ; indexCurLevel < curLevelNumber ; indexCurLevel ++ )
                line2 = putBranchInLine( line2 , indexCurLevel , curTreeMaxLevelNumber*3-1 );
            System.out.println(line2);

            curTreeMaxLevelNumber /= 2;
        }
    }

    private String putNumberInLine( Integer num, String line, int indexCurLevel, int curTreeWidth, boolean isLeft){

        int subTreeWidth = (curTreeWidth - 1) / 2;
        int offset = indexCurLevel * (curTreeWidth+1) + subTreeWidth;
        assert offset + 1 < line.length();
        if( num >= 10 )
            line = line.substring(0, offset+0) + num.toString()
                    + line.substring(offset+2);
        else{
            if( isLeft)
                line = line.substring(0, offset+0) + num.toString()
                        + line.substring(offset+1);
            else
                line = line.substring(0, offset+1) + num.toString()
                        + line.substring(offset+2);
        }
        return line;
    }

    private String putBranchInLine( String line, int indexCurLevel, int curTreeWidth){

        int subTreeWidth = (curTreeWidth - 1) / 2;
        int subSubTreeWidth = (subTreeWidth - 1) / 2;
        int offsetLeft = indexCurLevel * (curTreeWidth+1) + subSubTreeWidth;
        assert offsetLeft + 1 < line.length();
        int offsetRight = indexCurLevel * (curTreeWidth+1) + subTreeWidth + 1 + subSubTreeWidth;
        assert offsetRight < line.length();

        line = line.substring(0, offsetLeft+1) + "/" + line.substring(offsetLeft+2);
        line = line.substring(0, offsetRight) + "\\" + line.substring(offsetRight+1);

        return line;
    }

    // 测试 PrintableMaxHeap
    public static void main(String[] args) {

        PrintableMaxHeap maxHeap = new PrintableMaxHeap(10);
        int N = 10; // 堆中元素个数
        int M = 100; // 堆中元素取值范围[0, M)
        for( int i = 0 ; i < N ; i ++ )
        maxHeap.insert( new Integer((int)(Math.random() * M)) );
        maxHeap.treePrint();
        System.out.print("*************************************");

        int m = 0;
        while( m <5){
            maxHeap.extractMax();
            maxHeap.treePrint();
            //System.out.print(extractMax);
            m++;
        }
    }
}

执行结果:
这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Dijkstra算法是一种用于解决单源最短路径问题的算法。它通过从起点开始,逐步找到当前最短路径的节点,并不断更新其他节点的距离值,最终得到起点到所有其他节点的最短距离。Dijkstra算法的基本思想是使用贪心策略,选择当前路径最短的节点作为中间节点,并以此为基础不断更新其他节点的距离值,直到遍历完所有节点。 二叉堆是一种用于实现优先队列的数据结构,它可以高效地进行插入和删除操作。二叉堆是一个完全二叉树,且父节点的值小于等于其子节点的值。在Dijkstra算法中,使用二叉堆可以有效地选取下一个最短路径的节点,从而提高算法的效率。 大堆是一种特殊的二叉堆,它满足父节点的值大于等于其子节点的值。大堆的特点是根节点的值最大,因此可以用来实现最大优先队列。在Dijkstra算法中,使用大堆可以高效地选择路径最短的节点,因为每次选择的节点都是当前距离最短的节点,所以大堆能够快速选出下一个待更新的节点,并更新其距离值。 综上所述,Dijkstra算法通过使用二叉堆这种数据结构,特别是大堆,能够高效地寻找最短路径问题的解答。通过Dijkstra算法,我们可以得到从起点到其他所有节点的最短路径,这在很多实际问题中具有重要的应用价值。 ### 回答2: dijkstra算法是一种解决图最短路径问题的算法,通过计算从起点到其他顶点的最短路径权值来找到最短路径。该算法的核心思想是以起点为中心,逐步扩展到其他顶点,每次选择当前最短路径的顶点并更新其邻居的最短路径权值。最后,当所有顶点都被扩展并更新完毕时,即可得到从起点到其他顶点的最短路径。 二叉堆是一种特殊的堆数据结构,它是通过二叉树来实现的,具有以下性质:任意节点的值都大于(或小于)其子节点的值。在dijkstra算法中,可以使用二叉堆来维护每个顶点的最短路径权值。通过使用二叉堆,可以高效地选择当前最短路径的顶点,并更新其邻居的最短路径权值。另外,使用二叉堆可以将插入和删除操作的时间复杂度控制在O(log n)级别。 大堆是一种堆排序中的概念,具体指堆中每个节点的值都不小于其子节点的值。在二叉堆中,大堆的概念可以用来实现最大堆。与二叉堆类似,最大堆也可以用来实现dijkstra算法中的优先队列,用于高效地选择当前最短路径的顶点。在使用最大堆进行元素插入或删除操作时,也可以保持时间复杂度在O(log n)级别。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值