堆和堆排序

最近看了些数据结构的书,为了便于以后复习,遂用Java实现了堆的构造与堆排序。

/**
 * Created by cht on 2016/11/6.
 */

//堆:可以定义为一颗二叉树,树中的节点满足两个条件;a,树的形状要求,对于该树,要求树必须是基本完备的,即,除树的最后一层之外,其他层都是满的。
//b,父母优势,即,对于书中的任一父节点,该节点所对应的key不小于其孩子节点的key。叶子节点默认满足此要求。
//堆有如下的特性:
// 1,如果该堆得节点个数为n,则其所对应的树的高度为不大于log n的整数。
// 2,堆的根节点是堆中最大的元素,堆的左右子树也是一个堆。
// 3,可以用数组来实现一个堆,数组heap[n+1]的1<=index<=n,存储堆中的n个元素,heap[0]的位置可以存放一个0,也可以存放其他的值;父节点在数组中的前n/2个位置,叶子节点在后n/2个位置;父节点的位置为i(假设其有孩子节点),则其孩子节点的位置为2*i和2*i+1的位置

public class Heap {
    //储存堆的数据结构,这里选择的是数组,为了简单。最理想的应该是动态数组,便于堆的插入与删除。
    public int heap[];

    /**
     * 堆的构造函数。采用自底向上的方法构造堆
     * @param heap
     */
    public Heap(int heap[]) {
        int n = heap.length - 1;
        for (int i = n / 2; i >= 1; i--) {
            int k = i;
            int value = heap[k];
            Boolean tagHeap = false;
            while (!tagHeap && 2 * k <= n) {
                int j=2*k;   //k节点所对应的孩子节点

                //k节点存在两个孩子,找到最大的一个孩子
                if(j<n){
                    //如果右孩子大于左孩子,
                    if(heap[j]<heap[j+1]){
                        j=j+1;
                    }
                }
                if(value>heap[j]) {
                    tagHeap = true;
                }else {
                    heap[k]=heap[j];
                    k=j;
                }
            }
            heap[k]=value;
        }
        this.heap=heap;
    }

    /**
     * 堆的构造函数。采用自底向上的方法构造堆
     * n为堆中包含的元素。在数组中的位置对应的索引为1-n。
     * @param heap
     * @param n
     */
    public Heap(int heap[],int n){
        n=n-1;
        for (int i = n / 2; i >= 1; i--) {
            int k = i;
            int value = heap[k];
            Boolean tagHeap = false;
            while (!tagHeap && 2 * k <= n) {
                int j=2*k;   //k节点所对应的孩子节点

                //k节点存在两个孩子,找到最大的一个孩子
                if(j<n){
                    //如果右孩子大于左孩子,
                    if(heap[j]<heap[j+1]){
                        j=j+1;
                    }
                }
                if(value>heap[j]) {
                    tagHeap = true;
                }else {
                    heap[k]=heap[j];
                    k=j;
                }
            }
            heap[k]=value;
        }
        this.heap=heap;
    }

    /**
     * 打印堆
     */
    public void printHeap(){

        for (int i = 0; i < this.heap.length; i++) {
            System.out.print(this.heap[i]+" ");
        }
        System.out.println();
    }

    /**
     * 删除堆中最大的元素,即删除堆的根节点。
     * 1.将堆的根节点与最后的一个元素(k)互换位置
     * 2.堆的规模减一,并且重新进行堆化。
     * 3.我在进行堆化的时候用的是方法是重新构建一个堆,不推荐这种方法,效率不高。应该对k采取沿着堆树向下进行筛选,以此进行堆化,对于此种方法,储存堆的数据结构应该选择动态数组。
     *
     */
    public void delRoot(){
        int n=this.heap.length;
        int temp=this.heap[n-1];
        this.heap[n-1]=this.heap[1];
        this.heap[1]=temp;
        int tempArry[]=new int[n-1];
        for (int i = 0; i <n-1 ; i++) {
            tempArry[i]=this.heap[i];
        }
        Heap tempHeap=new Heap(tempArry);
        this.heap=tempHeap.heap;
    }

    /**
     * 删除堆中最大的元素,即删除堆的根节点,但是将该元素保留在储存堆的数组的最后一个位置。
     * 该函数用于最大堆排序。
     * 该函数的解析类似函数delRoot()。
     * @param n
     */
    public void delRoot(int n){
        int temp=this.heap[n];
        this.heap[n]=this.heap[1];
        this.heap[1]=temp;
        Heap tempHeap=new Heap(this.heap,n);
        this.heap=tempHeap.heap;
    }

    /**
     * 实现堆排序。
     */
    public void sortHeap(){
        int n=this.heap.length-1;
        for (int i = n; i >1; i--) {
            this.delRoot(i);
        }

    }

    public static void main(String[] args) {
        System.out.println("--------------测试(注:test[0]不是堆中的元素,是个占位数字,可以置零)------------");
        int test[]={11,2,9,7,6,5,8};
        System.out.println("--------------test[]------------");
        for (int i = 0; i < test.length; i++) {
            System.out.print(test[i]+" ");
        }
        System.out.println();

        Heap heap=new Heap(test);
        System.out.println("------------调用构造函数Heap(int heap[])---------");
        System.out.println("------------heap.printHeap()---------");
        heap.printHeap();

        heap.delRoot();
        System.out.println("------------heap.delRoot()---------");
        heap.printHeap();

        System.out.println("--------------test[]------------");
        for (int i = 0; i < test.length; i++) {
            System.out.print(test[i]+" ");
        }
        System.out.println();

        Heap heap1=new Heap(test);
        System.out.println("------------调用构造函数Heap(int heap[])---------");
        System.out.println("------------heap1.printHeap()---------");
        heap1.printHeap();

        heap1.sortHeap();
        System.out.println("------------heap1.sortHeap()---------");
        heap1.printHeap();
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值