首先介绍一下什么是
引入百度百科:

(英语:heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:
堆中某个节点的值总是不大于或不小于其父节点的值;
堆总是一棵完全二叉树。
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、斐波那契堆等。
堆的定义如下:n个元素的序列{k1,k2,ki,…,kn}当且仅当满足下关系时,称之为堆。
(ki <= k2i,ki <= k2i+1)或者(ki >= k2i,ki >= k2i+1), (i = 1,2,3,4…n/2)
若将和此次序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个完全二叉树,则堆的含义表明,完全二叉树中所有非终端结点的值均不大于(或不小于)其左、右孩子结点的值。由此,若序列{k1,k2,…,kn}是堆,则堆顶元素(或完全二叉树的根)必为序列中n个元素的最小值(或最大值)

简单概括
1.堆一定是完全二叉树。
2.大(小)顶堆中当前结点的值一定大(小)于其左右孩子的值。

下图为大顶堆和小顶堆:
这里写图片描述
给出堆的建立以及排序实现:

/**
 * 堆
 * @author zxy
 *
 */
public class Heap {

    private int[] array;

    private int count; //堆中元素的个数

    private int capacity; //堆的大小

    private int heap_type; //大顶堆或小顶堆 0大 1小 

    public Heap(int capacity, int heap_type){
        this.heap_type=heap_type;
        this.count=0;
        this.capacity=capacity;
        this.array=new int[capacity];
    }

    /**
     * 获取父结点
     * @param i
     * @return
     */
    public int parent(int i){
        if(i<=0 || i>=this.count){
            return -1;
        }
        return (i-1)/2;
    }

    /**
     * 获取左孩子
     * @param i
     * @return
     */
    public int leftChild(int i){
        int left=2*i+1;
        if(left>=this.count){
            return -1;
        }
        return left;
    }

    /**
     * 获取右孩子
     * @param i
     * @return
     */
    public int rightChild(int i){
        int right=2*i+2;
        if(right>=this.count){
            return -1;
        }
        return right;
    }

    /**
     * 获取堆中最大值(大顶堆的根结点)
     * @return
     */
    public int getMaximum(){
        if(this.count==0){
            return -1;
        }
        return array[0];
    }

    /**
     * 向下调整(当前结点与左右孩子较大值的结点换位,保证三个结点的最大值处于上位)
     * @param i
     */
    public void percolateDown(int i){
        int l,r,max,temp;
        l=leftChild(i);
        r=rightChild(i);
        if(l!=-1 && this.array[l]>this.array[i]){
            max=l;
        }else{
            max=i;
        }
        if(r!=-1 && this.array[r]>this.array[max]){
            max=r;
        }
        if(max!=i){
            temp=this.array[i];
            this.array[i]=this.array[max];
            this.array[max]=temp;
            percolateDown(max);
        }
    }

    /**
     * 建堆,从最后一个叶子结点的父结点开始向下调整
     * @param h
     * @param a
     * @param n
     */
    public static void build(Heap h,int a[],int n){
        h.array=a;
        h.count=n;
        for(int i=(n-2)/2;i>=0;i--){
            h.percolateDown(i);
        }
    }

    /**
     * 堆排序
     * 每趟排序将最后一个结点与根结点换位,再将根结点向下调整,并且堆大小减1
     * 因为大顶堆的根结点是最大值,所以每趟排序过后,当前堆的最大值移至末尾
     * 所有排序结束,堆中元素呈现从小到大
     * @param a
     * @param n
     */
    public static void sort(int a[],int n){
        Heap h=new Heap(n,0);
        int old_size,i,temp;
        build(h, a, n);
        old_size=h.count;
        for(i=n-1;i>0;i--){
            temp=h.array[0];
            h.array[0]=h.array[i];
            h.array[i]=temp;
            h.count--;
            h.percolateDown(0);
        }
        h.count=old_size;
        a=h.array;
    }

    /**
     * 测试
     * @param args
     */
    public static void main(String[] args) {
        int[] array=new int[]{1,4,2,5,13,6,17};
        Heap.sort(array, array.length);
        for(int i=0;i<array.length;i++){
            System.out.print(array[i]+" ");
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值