數據結構Java版之堆&堆排序(九)

  堆分爲大頂堆,和小頂堆。 什麼是堆? 堆能夠當作是一棵二叉樹,二叉樹的元素是一個數組不斷的從左到右輪訓放置。若是是大頂堆,則大的數放上面一層,小的數放下面一層。上一層的數,必定大於下一層的數。小頂堆則相反。java

  那麼,如何實現一個大頂堆?這裏我用一個鏈表來實現。數組

實現堆很簡單,只要牢記他的原理就好了。測試

  添加新元素:添加至數組末尾。而後對這個末尾節點不斷的向上層冒泡。直到找到一個合適的節點放置。this

  刪除元素:從數組末尾取出一個元素對當前要刪除的元素進行覆蓋,後刪除末尾的元素。而後從當前節點不斷的向下冒泡。就能找到一個合適的位置進行放置。spa

  上層元素和下層元素之間的關係:上層元素(索引爲:index )和下層元素索引存在 2 * index + 1(左孩子節點) 2 * index + 2(右孩子節點)的關係。code

實現源碼:blog

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

  堆排序:rem

堆排序很是簡單,利用大頂堆的頂必定是堆元素裏面的最大值。那麼咱們就能夠將一系列數據存進去,再不斷的取出頂元素。取除的元素就是一個排好序的元素。

源碼:

  

    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

至此,堆排序就已經作好了。

相關文章
相關標籤/搜索