1. 程式人生 > >數據結構Java版之堆&堆排序(九)

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

add lse spa led main AD 節點 之間 ren

  堆分為大頂堆,和小頂堆。 什麽是堆? 堆可以看成是一棵二叉樹,二叉樹的元素是一個數組不斷的從左到右輪訓放置。如果是大頂堆,則大的數放上面一層,小的數放下面一層。上一層的數,一定大於下一層的數。小頂堆則相反。

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

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

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

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

  上層元素和下層元素之間的關系:上層元素(索引為: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

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

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