堆排序 java

堆排序是使用二叉樹模型,建立最大堆或最小堆,將最大值或最小值上浮,降低遍歷次數,增加排序效率的一種解決方法。

由於堆排序時使用的是完全二叉模型,所以可以使用數組進行表示。

在使用堆排序時,需要使用到完全二叉樹的一些公式,如父節點n/2-1,左子節點2i+1,右子節點2i+2,葉子節點(>size/2)等。具體見代碼。


1、首先定義堆模型的一些常用操作接口。

package cn.dream.sort;

public interface IHeapSort {

	/**
	 * 獲取父節點的位置
	 * 完全二叉樹父節點位置在(n-1)/2處
	 * @param i
	 * @return
	 */
	int getParent(int i);
	
	/**
	 * 獲取左子位置
	 * 完全二叉樹左子節點在2*i+1處
	 * @param i
	 * @return
	 */
	int getLeftChild(int i);
	
	/**
	 * 獲取右子位置
	 * 完全二叉樹右子節點在左子節點的後面(2*i+1)+1
	 * @param i
	 * @return
	 */
	int getRightChild(int i);
	
	/**
	 * 建堆
	 * 從n/2-1處開始調整樹結構,因爲從n/2處都是葉子節點,不需要調整
	 * @param a
	 * @param size
	 */
	int[] buildHeap(int[] a, int size);
	
	/**
	 * 調整堆
	 * 通過對堆的調整,使其滿足堆結構的要求,最大值上浮或最小值上浮。
	 * 對於任一節點進行調整時:
	 * 1、最大堆:如果該節點比(左右子節點最大值)小,交換該節點和最大值位置,然後調整樹
	 * 2、最小堆:如果該節點比(左右子節點最小值)大,交換該節點和最小值位置,然後調整樹
	 * @param a
	 * @param i
	 * @param size
	 */
	int[] adjustHeap(int[] a, int i, int size);
	
	/**
	 * 堆排序
	 * 1、最小堆:
	 * 方法一:執行遍歷{將根節點(min)取出,構建樹}
	 * 方法二:執行遍歷{將根節點(min)和最後一個節點(數組最後一位)交換,將參與構建的數組長度-1(移動size的index),重新構建樹結構},最後倒序輸出
	 * 2、最大堆:執行遍歷{將根節點(max)和最後一個節點(數組最後一位)交換,將參與構建的數組長度-1(移動size的index),重新構建樹結構}
	 * @param a
	 * @param size
	 */
	int[] sortHeap(int[] a, int size);
	
}


然後分別建立最大堆和最小堆,進行編碼測試

最小堆

package cn.dream.sort;

import java.util.Arrays;

public class MinHeapSortImpl implements IHeapSort {

	@Override
	public int getParent(int i) {
		return (int) (i - 1) / 2;
	}

	@Override
	public int getLeftChild(int i) {
		return 2 * i + 1;
	}

	@Override
	public int getRightChild(int i) {
		return 2 * i + 2;
	}

	@Override
	public int[] buildHeap(int[] a, int size) {
		for (int i = (size - 2) / 2; i >= 0; i--) {
			adjustHeap(a, i, size);
		}
		return a;
	}

	@Override
	public int[] adjustHeap(int[] a, int i, int size) {
		int min = i;
		int temp = a[i];
		int left = getLeftChild(i);
		int right = getRightChild(i);

		if (left < size && a[left] < temp) {
			min = left;
		}

		if (right < size && a[right] < a[min]) {
			min = right;
		}

		if (min != i) {
			a[i] = a[min];
			a[min] = temp;
			adjustHeap(a, min, size);
		}
		return a;
	}

	@Override
	public int[] sortHeap(int[] a, int size) {
		int[] b = new int[a.length];
		int i = 0;
		while(size>0) {
			b[i] = a[0];
			a[0] = a[size - 1];
			--size;
			adjustHeap(a, 0, size);
			
			i++;
		}
		return b;
	}

	public static void main(String[] args) {
		int[] arr = { 53, 4, 24, 47, 41, 97, 13, 83, 12, 35, 11, 15, 41, 18,
				68, 49, 36, 52, 9, 45, 0, 38, 36, 82, 76, 22, 44, 35, 34, 81,
				94, 70, 88, 30, 42, 45, 55, 75, 93, 57, 74, 0, 77, 64, 93, 58,
				15, 62, 13, 49, 60, 21, 3, 66, 15, 74, 48, 96, 52, 56, 63, 73,
				85, 44, 39, 42, 98, 38, 17, 81, 7, 60, 86, 79, 63, 66, 17, 78,
				78, 90, 23, 92, 79, 21, 80, 71, 6, 70, 59, 25, 41, 11, 64, 60,
				62, 51, 93, 46, 18, 31 };

		long startTime = System.currentTimeMillis();

		IHeapSort heapSort = new MinHeapSortImpl();

		System.out.println("測試最小堆的根節點是否最小值:");
		heapSort.buildHeap(arr, arr.length);
		System.out.println("root is:" + arr[0]);

		System.out.println("測試最小堆是否已經排序:");
		System.out.println(Arrays.toString(arr));

		System.out.println("排序:");
		int[] heap = heapSort.sortHeap(arr, arr.length);
		System.out.println(Arrays.toString(heap));

		System.out.println((System.currentTimeMillis() - startTime) + "ms");

	}
}

最大堆

package cn.dream.sort;

import java.util.Arrays;

public class MaxHeapSortImpl implements IHeapSort {

	@Override
	public int getParent(int i) {
		return (int) (i - 1) / 2;
	}

	@Override
	public int getLeftChild(int i) {
		return 2 * i + 1;
	}

	@Override
	public int getRightChild(int i) {
		return 2 * i + 2;
	}

	@Override
	public int[] buildHeap(int[] a, int size) {
		for (int i = (size - 2) / 2; i >= 0; i--) {
			adjustHeap(a, i, size);
		}
		return a;
	}

	@Override
	public int[] adjustHeap(int[] a, int i, int size) {
		int largest = i;
		int temp = a[i];
		int left = getLeftChild(i);
		int right = getRightChild(i);

		if (left < size && a[left] > temp) {
			largest = left;
		}

		if (right < size && a[right] > a[largest]) {
			largest = right;
		}

		if (largest != i) {
			a[i] = a[largest];
			a[largest] = temp;
			adjustHeap(a, largest, size);
		}
		return a;
	}

	@Override
	public int[] sortHeap(int[] a, int size) {
		// buildHeap(a, size);
		int temp;
		for (int i = size - 1; i >= 0; i--) {
			temp = a[0];
			a[0] = a[i];
			a[i] = temp;
			adjustHeap(a, 0, i);
		}
		return a;
	}

	public static void main(String[] args) {
		int[] arr = { 53, 4, 24, 47, 41, 97, 13, 83, 12, 35, 11, 15, 41, 18,
				68, 49, 36, 52, 9, 45, 0, 38, 36, 82, 76, 22, 44, 35, 34, 81,
				94, 70, 88, 30, 42, 45, 55, 75, 93, 57, 74, 0, 77, 64, 93, 58,
				15, 62, 13, 49, 60, 21, 3, 66, 15, 74, 48, 96, 52, 56, 63, 73,
				85, 44, 39, 42, 98, 38, 17, 81, 7, 60, 86, 79, 63, 66, 17, 78,
				78, 90, 23, 92, 79, 21, 80, 71, 6, 70, 59, 25, 41, 11, 64, 60,
				62, 51, 93, 46, 18, 31 };

		long startTime = System.currentTimeMillis();

		IHeapSort heapSort = new MaxHeapSortImpl();

		System.out.println("測試最大堆的根節點是否最大值:");
		heapSort.buildHeap(arr, arr.length);
		System.out.println("root is:" + arr[0]);

		System.out.println("測試最大堆的順序是否爲倒序:");
		System.out.println(Arrays.toString(arr));
		
		System.out.println("排序:");
		heapSort.sortHeap(arr, arr.length);
		System.out.println(Arrays.toString(arr));

		System.out.println((System.currentTimeMillis() - startTime) + "ms");

	}

}



更多排序,,參考這位的http://blog.csdn.net/han_xiaoyang/article/details/12163251

發佈了47 篇原創文章 · 獲贊 43 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章