1. 程式人生 > >實現最大堆(包括插入和從堆中取出元素)及第一種堆排序【Java版】

實現最大堆(包括插入和從堆中取出元素)及第一種堆排序【Java版】

/**
*實現最大堆
*用陣列儲存
*小優化:將swap用賦值代替,先不急著交換,先複製,再移動,最後賦值
*第一種堆排序,從小到大排序
*時間複雜度為O(nlogn)
*空間複雜度O(n)
*/

public class MaxHeap {
    private int count;  //記錄堆中儲存元素的個數
    private static int[] data; //用陣列儲存二叉堆
    private int capacity;
    public MaxHeap(int capacity) {
        //在構造方法中初始化
        count=0
; data=new int[capacity+1];//因為根節點從1開始,所以儲存空間加1 //不能省略,否則預設類中的capacity為0; this.capacity=capacity; } //判斷堆是否為空 boolean isEmpty() { return count==0; } //輸出堆中元素個數 int size() { return count; } public int getCapacity() { return this.capacity; } //向堆中新增元素
public void insert(int item ) { //先將新增的元素加到最後一個元素後面 //有索引還得考慮索引越界問題,最好的解決方案是動態擴充套件堆 //這樣可以不受堆容量限制,容量不足開闢新空間 if(count++<=getCapacity()) { //count指向所新增的元素 data[count]=item; //再將item向上移動,與父節點比較,如果比父節點大,則交換 shiftUp(count); } } //向上移動,將item與父節點比較,如果比父節點大,則交換
private void shiftUp(int i) { while(i>1&&data[i]>data[i/2]) { swap(i,i/2); i/=2; } } //從堆中取出元素,優先佇列思想 public int extractMax() { if(count<=0) return 0; //先取出最大的(優先順序高的) int max=data[1]; //將堆中最後一個元素存入第一元素的位置 swap(1, count); count--; //將第一個元素向下移,找到合適位置,維護堆 shiftDown(1); return max; } private void shiftDown(int i) { //定義左孩子,完全二叉樹如果有孩子,一定有左孩子 while (2*i<=count) { int j=2*i; //j+1即為右孩子 if(j+1<=count&&data[j+1]>data[j]) j+=1; if(data[i]>=data[j]) break; swap(i, j); i=j; } } private void swap(int i, int j) { if(i!=j) { int temp=data[i]; data[i]=data[j]; data[j]=temp; } } public void print(int []data,int count) { for(int i=0;i<=count;i++) System.out.print(data[i]+" "); System.out.println(); }

//測試這裡寫程式碼片

    public static void main(String args[]) {
        //建立堆
        MaxHeap maxHeap =new MaxHeap(100);
        //向堆中存,插入元素,入隊
        for(int i=0;i<20;i++) {
             maxHeap.insert((int)(Math.random()*100));
        }     
        maxHeap.print(data,maxHeap.count);
        System.out.println(maxHeap.size());

        //從堆裡取,依次取出最大值,從大到小
        while(!maxHeap.isEmpty()) {
            System.out.print(maxHeap.extractMax()+" ");
        }

    }
}

/**
*實現堆排序
*時間複雜度為O(nlogn)
*空間複雜度O(n)
*根節點從1開始,左孩子:2i,右孩子2i+1;
*/

public class HeapSort1 {
    public void heapSort1(int[]arr,int n) {
        MaxHeap heap1=new MaxHeap(n);
        //存入堆
        //這一步可以優化,不用每一個元素都要insert一次
        for(int i=0;i<n;i++) {
            heap1.insert(arr[i]);
        }
        //從小到大排序
        for(int i=n-1;i>=0;i--) {
            arr[i]=heap1.extractMax();
        }
    }
    public static void main(String[] args) {
        int [] arr= {8,7,4,5,9,2,10,3,3,3,30,3};
        int n=arr.length;   
        HeapSort1 sort1=new HeapSort1();
        sort1.heapSort1(arr, n);    
        for(int i=0;i<n;i++)
            System.out.print(arr[i]+" ");
    }
}