算法之堆排
算法虐我千百遍,我爱算法如初恋(微笑)
研究堆排序也是一脸懵逼,所以我决定好好分析一下,尽量白话一点,方便理解。
总的来说就是一个二叉树结构1-2-4-8……这样的,从左至右排,最后一排排不满就不管了。我先以我给的数组为例18,11,9,7,3,4,2,2,3,9 从第一个开始的序号是0最后一个是heapSize-1.
整个算法最关键的点就是保证每个三角形结构,三角形顶尖是最大的,左右谁大谁小在递归的时候就自己排好了。既然要开始选择三角形了,那么就从序号最大的开始,毕竟什么事都要从基层做起嘛~
我称三角形顶尖的数为小弟1和小弟2的老大,那最大序号的老大是多少呢?(heapSize-2)/ 2 由于是整数,不管三角形是缺了一角还是没缺,除不尽反正就四舍了。
那三个数比大小还不简单~谁大谁就是老大嘛
int left = left(i);
int right = right(i);
int parent = i;
if(left < heapSize && a[left] > a[parent]) { //
parent = left;
}
if(right < heapSize && a[right] > a[parent])
{
parent = right;
}
那旧老大被新老大顶替了,还要看看下面小弟要不要造反,以此往复就成了递归,那我们程序加入递归:
int left = left(i);
int right = right(i);
int parent = i;
if(left < heapSize && a[left] > a[parent]) { //
parent = left;
}
if(right < heapSize && a[right] > a[parent])
{
parent = right;
}
if(parent != i) {
int temp = a[parent];
a[parent]=a[i];
a[i]=temp;
maxHeapfy(a,parent,heapSize);
}
那最大序号做完了,这小弟们造反不是要一起吗,我们让每个父节点都要遍历一遍,那就是刚才的(heapSize-2)/ 2往下减一,我这么不知道你思路清晰了一点没,下面是我的完整代码。
package suanfa.test;
import java.util.Arrays;
/**
*
* @author Tacenee
*
*/
public class DuiPai {
static int left(int i) {
return 2*i + 1;
}
static int right(int i) {
return 2*i + 2;
}
/**
*
* @param a 数组a
* @param i 第i个结点
* @param heapSize heapSize是数组种实际要排序的元素的长度
*/
static void maxHeapfy(int []a,int i,int heapSize) {
int left = left(i);
int right = right(i);
int parent = i;
//判断是否还有子结点
if(left < heapSize && a[left] > a[parent]) { //
parent = left;
}
if(right < heapSize && a[right] > a[parent])
{
parent = right;
}
//将三者最大值跟父节点调换,但是不考虑左右子结点谁大谁小
if(parent != i) {
int temp = a[parent];
a[parent]=a[i];
a[i]=temp;
//当换了爸爸以后,看被换掉的儿子的儿子是不是也要换
maxHeapfy(a,parent,heapSize);
}
}
static void buildMaxHeap(int []a,int heapSize) {
for(int i = (heapSize-2)/2;i >= 0;i--) {
maxHeapfy(a,i,heapSize);
}
}
static void heapSort(int []a) {
int len = a.length-1;
//初始化堆
buildMaxHeap(a,len);
for(int i =len;i>0;i--) {
//对调最大的和最后一个结点
int temp =a[0];
a[0]=a[len];
a[len]=temp;
len--;
//最大值已确定,总长度减1迭代
maxHeapfy(a,0,len);
}
}
public static void main(String args[]) {
int []a = {18,11,9,7,3,4,2,2,3,9};
heapSort(a);
System.out.println(Arrays.toString(a));
}
}
//结果:[2, 2, 3, 3, 4, 7, 9, 9, 11, 18]
**如有不足还望指点,多谢