堆排序相对简单的冒泡算法快就快在它利用了每一次排序,将结果保存下来。
堆结构是一颗完全二叉树,即除了最后一层其他层的每个结点都包含两个子结点,我们知道拥有子节点的元素脚标是0至n/2-1,我们从n/2-1开始向上构建大顶堆结构,每一个父亲结点的值都大于孩子结点,先取得左结点L和右结点R,比较结点大小,如果父结点小于孩子结点则进行交换,并且交换之后从被交换的孩子结点递归排查,因为改变一个结点可能它的孩子结点就会违背堆结构的原则。如果不用交换就排查前一个结点,这是初始化一个大顶堆。
初始化完成之后就很简单了,我们发现当前最大的元素就是根结点,我们把它和数组最后一个元素交换,设置排查长度减一,实现就地取材,不用另开存储空间,总共取你次最大元素,排序就完成了。
//堆排序
public class MaxHeap {
public static void Maxify(int[]a,int i,int len)
{
int left = i*2+1;//左结点元素脚标
int right = i*2+2;//右结点元素脚标
int max;//父子结点中最大元素的脚标
if(left<len&&a[left]>a[i])
max = left;
else
max = i;
if(right<len&&a[right]>a[max])
max = right;
if(max == i||max >= len)//如果最大值的脚标还是i,不用交换
return;
int temp = a[i];
a[i] = a[max];
a[max] = temp;
Maxify(a,max,len);//排查被交换子结点的孩子结点是否需要再次交换
}
public static void HeapSort(int[]a)
{
int len = a.length;//排查范围
for(int i=len/2-1;i>=0;i--)//初始化
{
Maxify(a,i,len);
}
for(int i=0;i<a.length;i++)//取n次最大值
{
int temp = a[0];
a[0] = a[len-1];
a[len-1] = temp;
len--;
Maxify(a,0,len);
}
}
public static void main(String[] args) {
int[] array=new int[]{1,2,3,30,7,8,44,10,19,16};
HeapSort(array);
for(int i=0;i<array.length;i++)
{
System.out.print(array[i]+" ");
}
}
}