十大算法之堆排序:
堆的定義例如以下:
堆的定義例如以下:
n個元素的序列{k0,k1,...,ki,…,k(n-1)}當且僅當滿足下關系時,稱之為堆。
" ki<=k2i,ki<=k2i+1;或ki>=k2i,ki>=k2i+1.(i=1,2,…,[n/2])"
若將和此次序列相應的一維數組(即以一維數組作此序列的存儲結構)看成是一個全然二叉樹,
則全然二叉樹中每個節點的值的都大於或等於隨意一個字節的值(假設有的話)。稱之為大頂堆。
則全然二叉樹中每個節點的值的都小於或等於隨意一個字節的值(假設有的話),稱之為小頂堆。
由此,若序列{k0,k1,…,k(n-1)}是堆。則堆頂元素(或全然二叉樹的根)必為序列中n個元素的最小值(或最大值)。
倘若給堆中每個節點都賦予一個整數值標簽,根節點被標記為0。對於每個標記為i的節點,其左子節點(若存在的話)被標記為2*i+1,其右子節點(若存在的話)被標記為2*i+2,對於一個標記為i的非根節點,其父節點被標記為(i-1)/2。使用這個標記,我們可以將堆存儲在數組中。節點存儲在數據中的位置就使其標簽。
package sort;
import java.util.Arrays;
/*
* 堆排序
* 堆的定義:滿足 Ki <= K2i+1 Ki<=K2i+2 為小頂堆,滿足 Ki >= K2i+1 Ki>=K2i+2 為大頂堆
* 此為大頂堆的代碼實例,小頂堆相似
*/
public class duiSort {
static int[] arr = {
16,7,3,20,17,8 //定義待排序數組
};
public static void main(String[] args) {
buildHeap();//建立大頂堆並排序
System.out.println("排序好的為:" + Arrays.toString(arr));
}
private static void buildHeap() {
// TODO Auto-generated method stub
int len = arr.length;
for(int i =len/2 -1 ;i>=0;i--) //建立大頂堆
{
sortHeap(i,len);
}
System.out.println("建立好的大頂堆例如以下:" + Arrays.toString(arr));
for(int j = len-1; j >0; j --) //對大頂堆進行排序
{
swap(0,j);
sortHeap(0,j);
}
}
private static void sortHeap(int i, int len) {
// TODO Auto-generated method stub
int left = 2*i+1; //定義左節點
int right = 2*i +2; //定義右節點
int large = 0; //存放三個節點中最大節點的下標
if(len >left && arr[left] > arr[i]) //假設左孩子大於根節點 將左孩子下標賦值給large
large = left;
else //否之。將根節點下標賦值給large
large = i;
if(len > right && arr[right] > arr[large])
large = right; //若右孩子節點大於根節點,把右孩子節點下標賦值給large
if(large != i) //若最大節點的下標不等於根節點的下標時,交換其值
{
swap(large,i);
sortHeap(large,len);
}
}
//交換相應下標值
private static void swap(int m, int n) {
// TODO Auto-generated method stub
int temp ;
temp = arr[m];
arr[m] = arr[n];
arr[n] = temp;
}
}
