首先明确什么是堆?
一个数组:
int[] unsort={12,24,35,40,50,66,70,56,55};
堆的表现形式(这是一个最小堆,根节点是最小的):

用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。(这样就是给数组建好堆了)
下面进入堆排序的核心步骤:堆节点的移动
这里需要对unsort[3]=12进行调整
对unsort[3]的子节点unsort[7],unsort[8]进行比较,符合最小堆!
对unsort[1]=24进行调整
跟左子节点进行调整
对unsort[0]=40进行调整
比较左右子节点,12<35;
12<40进行调整,上移;
比较左右子节点,24<50;
24<40,上移;
55<56;55>40;至此调整结束,24所在索引位置替换成40;
最小堆的根节点值最小。
下面看代码:
//从i节点开始调整, i节点的子节点为 2*i+1, 2*i+2
public static void MinHeapFixdown(int a[], int i, int n)
{
int j, temp;
temp = a[i]; //取出节点值,比较,替换
j = * i + ; //左子节点
while (j < n)
{
if (j + < n && a[j + ] < a[j]) //在左右子节点中找最小的
j++;
if (a[j] >= temp) //说明已经排好序
break;
a[i] = a[j]; //把较小的子结点往上移动,替换它的父结点
i = j;
j = * i + ; //继续往下遍历比较
}
a[i] = temp; //调整结束
}
有了堆的调整操作,建立堆,进行堆排序:
/**
* 建立最小堆
* 对数组中的每个元素进行子节点调整,最小的向上移动
* @param a 数组
* @param n 数组长度
*/
static void MakeMinHeap(int a[], int n)
{
//n/2-1可以定位到最后一个数组元素了,子节点分别为n-2,n-1
for (int i = n / - ; i >= ; i--)
MinHeapFixdown(a, i, n);
}
public static void MinheapsortTodescendarray(int a[], int n)
{
for (int i = n ; i >= ; i--)
{
MakeMinHeap(a,i);//从根节点调整定位最小值,调整过后a[0]最小
swap(a,i-,);//交换值,此时a[0]最小,进行下沉;下次遍历进行调整不会调整a[i-1]
}
}
此时得到的数组是递减的:
public static void main(String[] args) {
int[] unsort={,,,,,,,,};
MinheapsortTodescendarray(unsort, unsort.length);
for (int i = ; i < unsort.length; i++) {
System.out.print(" "+unsort[i]);
}
}
运行结果:
101 100 80 56 55 40 24 12 8