数据结构Java版之堆&堆排序(九)

  堆分为大顶堆,和小顶堆。 什么是堆? 堆可以看成是一棵二叉树,二叉树的元素是一个数组不断的从左到右轮训放置。如果是大顶堆,则大的数放上面一层,小的数放下面一层。上一层的数,一定大于下一层的数。小顶堆则相反。

  那么,如何实现一个大顶堆?这里我用一个链表来实现。

实现堆很简单,只要牢记他的原理就行了。

  添加新元素:添加至数组末尾。然后对这个末尾节点不断的向上层冒泡。直到找到一个合适的节点放置。

  删除元素:从数组末尾取出一个元素对当前要删除的元素进行覆盖,后删除末尾的元素。然后从当前节点不断的向下冒泡。就能找到一个合适的位置进行放置。

  上层元素和下层元素之间的关系:上层元素(索引为:index )和下层元素索引存在 2 * index + 1(左孩子节点) 2 * index + 2(右孩子节点)的关系。

实现源码:

package heap;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.junit.Test;

public class Heap {
    private List<Integer> heapArray;
    public Heap() {
        super();
        this.heapArray = new ArrayList();
    }
    //添加元素进堆 
    public void Push(Integer x) {
        heapArray.add(x);
        trickleUp(heapArray.size()-1);
    }
    //删除元素
    public void Pop() {
        heapArray.set(0, heapArray.get(heapArray.size()-1));
        heapArray.remove(heapArray.size()-1);
        trickleDown(0);
    }
    //取出根数据
    public Integer Top() {
        return heapArray.get(0);
    }
    //判断是否为空
    public boolean isEmpty() {
        if(Top() == null) {
            return true;
        }
        return false;
    }
    //向上渗透
    public void trickleUp(int index) {
        int parent = (index-1) / 2;
        Integer bottom = heapArray.get(index);
        while(index > 0 && heapArray.get(parent) < bottom) {
            heapArray.set(index, heapArray.get(parent));
            index = parent;
            parent = (parent - 1) / 2;
        }
        heapArray.set(index, bottom);
    }
    //向下渗透
    public void trickleDown(int index) {
        Integer top = heapArray.get(0);
        int lagerChild;
        while(index < heapArray.size()/2) {
            int leftChild = index * 2 + 1;
            int rightChild = index * 2 + 2;
            if(rightChild < heapArray.size() && heapArray.get(leftChild) < heapArray.get(rightChild)) {
                lagerChild = rightChild;
            }else {
                lagerChild = leftChild;
            }
            if(top >= heapArray.get(lagerChild)) {
                break;
            }
            heapArray.set(index, heapArray.get(lagerChild));
            index = lagerChild;
        }
        heapArray.set(index, top);
    }
}

测试程序:

@Test
public void fun() {
    Heap p = new Heap();
    p.Push(20);
    p.Push(30);
    p.Push(15);
    System.out.println(p.Top());
    p.Push(90);
    p.Push(35);
    System.out.println(p.Top());
    p.Pop();
    System.out.println(p.Top());
}

测试结果:

30
90
35

  堆排序:

堆排序非常简单,利用大顶堆的顶一定是堆元素里面的最大值。那么我们就可以将一系列数据存进去,再不断的取出顶元素。取除的元素就是一个排好序的元素。

源码:

  

    public static void main(String[] args) {
        Heap h = new Heap();
        h.Push(2);
        h.Push(1);
        h.Push(4);
        h.Push(6);
        System.out.println(h.Top());
        h.Pop();
        System.out.println(h.Top());
        h.Pop();
        System.out.println(h.Top());
        h.Pop();
        System.out.println(h.Top());
    }

结果:

6
4
2
1

至此,堆排序就已经做好了。

posted @ 2018-07-01 13:59  Ranter  阅读(598)  评论(0编辑  收藏  举报