堆排序

概念

最大(小)堆: 完全二叉树且所有的非叶子节点大于(等于)等于其子节点,即每一个子节点都为最大(小)堆
属性:最大(小)堆的最大(小)的值为根结点。
操作:

  • push:添加一个结点,仍然是最大(小)堆。
  • pop :移除根节点(也就是最大或者最小值),仍然是最大(小)堆。
  • build:将一棵完全二叉树构建成一个最大(小)堆。

分析-构建一个最大堆

可以通过数组或者链表作为基本的数据结构(本文选取数组)。根结点index为0;
父节点=(子节点-1)/2;
左子节点=父节点×2+1;
右子节点=父节点×2+2;

  • push:
    ①将结点放入堆最末尾,作为最后一个叶结点。
    ②将该节点p与其父节点parent比较,若父节点大于等于子节点,则结束;若子节点大于父节点,则交换两个结点。
    ③交换之后,将parent赋值给p,重复操作②,直到p变成根结点或者在②中满足第一个条件退出—迭代
//递归比较,比较新增的结点和其父节点的大小
    void push(Integer node){
        if(index+1>=size){
            return;//堆已满
        }
        maxHeap[++index]=node;//index作为成员变量,表示最后一个叶节点的位置
        int p=index;
        while(p!=0){//0是根节点
            int parent=(p-1)/2;//父节点的index
            if(maxHeap[parent].compareTo(maxHeap[p])>=0){//若父节点大于子节点,说明树是一个最大堆。
                break;
            }else {//否则,交换两个结点,继续与父节点的父节点比较
                swap(parent,p);
                p=parent;
            }
        }
    }
  • pop:
    ①将最后一个叶节点移到根节点,记录最后一个结点位置的index减1。表示已经移出了根结点。当前堆不一定为最大堆,需调整。
    ②将根节点root与其左右子节点(left,right)比较,若根节点为最大值,则不变;否则将最大的子节点与更结点交换位置。
    ③交换位置之后,被交换位置的子节点不一定是最大堆,需调整。将该结点赋值给root,重复操作②,直到②中第一个条件满足或者子节点不存在(超出index);
Integer pop(){
        if(index<0)//堆为空
            return null;
        Integer result=maxHeap[0];//返回的根节点
        maxHeap[0]=maxHeap[index--];//将最后一个叶节点移到根结点
        int rootIndex=0;
        while (rootIndex<=index){//如果结点不存在,则返回
            int leftIndex=rootIndex*2+1;//左节点索引
            int rightIndex=rootIndex*2+2;//右结点索引
            Integer left=null;
            Integer right=null;
            Integer root=maxHeap[rootIndex];
            if(leftIndex<=index){
                left=maxHeap[leftIndex];
            }
            if(rightIndex<=index){
                right=maxHeap[rightIndex];
            }
            if(left!=null&&right!=null){//如果左右结点存在
                if(left.compareTo(right)>0&&left.compareTo(root)>0){//如果左结点最大,交换根结点和左结点
                    swap(leftIndex,rootIndex);
                    rootIndex=leftIndex;
                }else if(right.compareTo(left)>0&&right.compareTo(root)>0) {//如果右结点最大,交换根结点和右结点
                    swap(rightIndex,rootIndex);
                    rootIndex=rightIndex;
                }else {     //否则不变
                    break;
                }
            }else if(left!=null){//如果仅有左节点存在(因为是完全树,所以不存在仅右结点存在的情况)
                if(left.compareTo(rootIndex)>0){
                    swap(leftIndex,rootIndex);
                    rootIndex=leftIndex;
                }else {
                    break;
                }
            }else{//其它情况,左右结点均为空结点
                break;
            }
        }
        return result;
    }
  • build:构建有两种方法,一种是通过push操作,一个一个添加即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值