堆排序原理需要先明白,这里直接上代码:
package algorithm;
import java.util.Arrays;
/**
* 通过大顶堆实现堆排序,升序排序
*
* @author bin.zhang
* @version 2017年8月31日 下午10:02:07
*/
public class HeapSort {
public static void main(String[] args) {
int[] arr = { 9, 6, 12, 33, 32, 34, 2, 100, 1000 };
sort(arr);
System.out.println(Arrays.toString(arr));
}
/**
* 将数组分为两部分,一部分为有序区,在数组末尾,另一部分为无序区,堆属于无序区
*
* @author bin.zhang
* @param arr
*/
public static void sort(int[] arr) {
int size = arr.length;
buildHeap(arr, size);
for (int i = size - 1; i > 0; i--) {// i为无序区的长度,经过如下两步,长度递减
// 堆顶即下标为0的元素
swap(arr, i, 0);// 1.每次将堆顶元素和无序区最后一个元素交换,即将无序区最大的元素放入有序区
adjustHeap(arr, 0, i); // 2.将无序区调整为大顶堆,即选择出最大的元素。
}
}
/**
* 建立堆,堆是从下往上建立的,因为adjustHeap函数是建立在子树已经为大顶堆
*
* @author bin.zhang
* @param a
* @param size
*/
public static void buildHeap(int[] a, int size) {
for (int i = size / 2; i >= 0; i--) {// 从最后一个非叶子节点,才能构成adjustHeap操作的目标二叉树
adjustHeap(a, i, size);
}
}
/**
* 这里将i定义为完全二叉树的根 将完全 二叉树调整为大顶堆,前提是二叉树的根的子树已经为大顶堆
*
* @author bin.zhang
* @param a
* @param i
* @param size
*/
public static void adjustHeap(int[] a, int i, int size) {
int lChild = 2 * i + 1; // 左孩子
int rChild = 2 * i + 2; // 右孩子
int max = i; // 临时变量
if (i < size / 2) { // 如果i是叶子节点就结束,这一步很关键(p.s. 不明白请Debug)!!!
if (lChild < size && a[max] < a[lChild])
max = lChild;
if (rChild < size && a[max] < a[rChild])
max = rChild;
if (max != i) {
swap(a, max, i);// 交换后破环了子树的堆结构
adjustHeap(a, max, size);// 递归,调节子树为堆
}
}
}
/**
* 交换数组中的元素
*
* @author bin.zhang
* @param a
* @param i
* @param j
*/
private static void swap(int[] a, int i, int j) {
a[i] = a[i] + a[j];
a[j] = a[i] - a[j];
a[i] = a[i] - a[j];
}
}
C++的实现代码供参考:
//堆排序
#include <iostream>
using namespace std;
void max_heapify(int*,int,int);
int tree_left(int);
int tree_right(int);
int tree_parent(int);
void exchange(int*,int,int);
void build_max_heap(int*,int);
void heap_sort(int*,int);
int main()
{
int* a=new int[8];
for(int i=0;i<8;i++){
a[i]=rand()%15;
}
heap_sort(a,8);
for(int i=0;i<8;i++){
cout<<a[i]<<" ";
}
cout<<endl;
system("pause");
return 0;
}
int tree_left(int i){
return (i+1)*2-1;
}
int tree_right(int i){
return (i+1)*2;
}
int tree_parent(int i){
return (i-1)/2;
}
void exchange(int* a,int i,int j){
a[i]=a[i]+a[j];
a[j]=a[i]-a[j];
a[i]=a[i]-a[j];
}
void max_heapify(int* a,int i,int n){
int l=tree_left(i);
int r=tree_right(i);
int largest=i;
if(l<n&&a[l]>a[i]) largest=l;
if(r<n&&a[r]>a[largest]) largest=r;
if(largest!=i){
exchange(a,i,largest);
max_heapify(a,largest,n);
}
}
void build_max_heap(int* a,int n){
for(int i=tree_parent(n);i>=0;i--){
max_heapify(a,i,n);
}
}
void heap_sort(int* a,int n){
build_max_heap(a,n);
for(int i=n-1;i>0;i--){
exchange(a,0,i);
max_heapify(a,0,i);
}
}