堆排序詳解(JAVA版)


package com.hsit.heap;

import java.util.Scanner;

/**
 * 
 * @author Colo
 * @version 創建時間:2011-11-1 上午11:44:10
 */
public class Heap {

	private int[] data;

	/*輸入數組元素,數組下標從1開始*/
	public void input() {
		System.out.println("請輸入數組大小");
		Scanner scanner = new Scanner(System.in);
		int n = scanner.nextInt();
		data = new int[n + 1];
		System.out.println("輸入數組元素");
		for (int i = 1; i <= data.length-1; i++) {
			data[i] = scanner.nextInt();
		}
		System.out.println("輸入完成");
	}
	
	/**
	 * 調整堆,使其滿足堆得定義
	 * @param i
	 * @param n
	 */
	public void adjust(int i, int n) {
		int child;
		for (; i <= n / 2; ) {
			child = i * 2;
			if(child+1<=n&&data[child]<data[child+1])
				child+=1;/*使child指向值較大的孩子*/
			if(data[i]<data[child]){
				swap(i, child);
				/*交換後,以child爲根的子樹不一定滿足堆定義,所以從child處開始調整*/
				i = child;
			}
		}
	}

	public void heapSort() {
		/*根據樹的性質,樹節點前一半一定是分支節點,即有孩子的,所以我們從分支節點開始調整出初始堆*/
		for (int i = data.length / 2; i > 0; i--)
			adjust(i, data.length-1);
		for (int i = data.length-1; i > 0; i--) {
			/*把根節點跟最後一個元素交換位置,調整剩下的n-1個節點,即可排好序*/
			swap(1, i);
			adjust(1, i - 1);
		}
	}

	public void swap(int i, int j) {
		int temp = data[i];
		data[i] = data[j];
		data[j] = temp;
	}

	public void print() {
		for (int i = 1; i < data.length; i++) {
			System.out.print(data[i]+" ");
		}
		System.out.println();
	}

}

建堆


  如上,首先第一步,在對應的數組元素A[i], 左孩子A[LEFT(i)], 和右孩子A[RIGHT(i)]中找到最大的那一個,將其下標存儲在child中。如果A[i]已經就是最大的元素,則程序直接結束。否則,i的某個子結點爲最大的元素,將其,即A[child]與A[i]交換,從而使i及其子女都能滿足最大堆性質。下標child所指的元素變成了A[i]的值,會違反最大堆性質,所以對child所指元素爲根的子樹重新調整。如下,是此adjust的演示過程下圖是把4調整到最底層,一趟操作,但摸索的時間爲LogN):

 

     由上圖,我們很容易看出,初始構造出一最大堆之後,在元素A[i],即16,大於它的倆個子結點4、10,滿足最大堆性質。所以,i下調指向着4,小於,左子14,所以,調用adjust,4與其子,14交換位置。但4處在了14原來的位置之後,4小於其右子8,又違反了最大堆的性質,所以再遞歸調用adjust,將4與8,交換位置。於是,滿足了最大堆性質,程序結束。


排序

以下是,堆排序算法的演示過程(通過,頂端最大的元素與最後一個元素不斷的交換,交換後又不斷的調用adjust重新維持最大堆的性質,最後,一個一個的,從大到小的,把堆中的所有元素都清理掉,也就形成了一個有序的序列。這就是堆排序的全部過程。):

 

 

上圖中,a->b,b->c,....之間,都有一個頂端最大元素與最小元素交換後,調用adjust的過程,而要完成整個堆排序的過程,共要經過O(n)次這樣的adjust操作。所以,纔有堆排序算法的運行時間爲O(n*lgn)。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章