堆的定义:
n个元素的序列{k1,k2,…,kn}当且仅当满足下列关系之一时,称之为堆。
大顶堆:ki >= k2i 且ki >= k2i+1。
小顶堆:ki <= k2i 且ki <= k2i+1。
堆序列可以理解成一个完全二叉树,该树任意一个结点的关键字的值都小于或等于它的孩子结点的关键字。例如:
堆排序:
若在输出堆顶的最小值之后,使得剩余n-1个元素的序列重又建成一个堆,则得到n个元素的次小值。如此反复执行,便能得到一个有序序列,这个过程称之为堆排序。
实现堆排序需要解决两个问题:
1.如何由一个无序序列建成一个堆?
n个元素的序列,从最后一个节点的父节点开始建堆,这个父节点为第n/2个元素。然后依次往上递减(n/2--)筛选出最大值或最小值,将树顶端的最大值或是最小值与最后一个元素交换。方法buildMaxHeap()的功能。
2.如何在输出堆顶元素之后,调整剩余元素成为一个新的堆?
对剩下的n-1个元素重新建堆,重复1中方法。
package sort;
public class HeadSort {
//public int[] headSort(int[] sortArray)
public void headSort(int[] sortArray)
{
for(int i=0;i<sortArray.length-1;i++) //需进行n-1趟排序
{
buildMaxHeap(sortArray,sortArray.length-1-i);
swap(sortArray,0,sortArray.length-1-i);
}
//return sortArray;
}
//交换两个数据的方法
public void swap(int[] data,int i,int j)
{
int temp = data[i];
data[i] = data[j];
data[j] = temp;
}
//建立大顶堆
public void buildMaxHeap(int[] data,int lastIndex)
{
//从lastIndex节点的父节点i开始建堆
for(int i=(lastIndex-1)/2;i>=0;i--)
{
int biggerIndex = 2*i+1; //假设左节点的值是最大的
//若存在右结点
if(biggerIndex < lastIndex)
{
//选出子节点中最大的值
if(data[biggerIndex] <= data[biggerIndex+1])
{
biggerIndex++;
}
}
//将左右结点父结点中的最大值放到父节点中
if(data[i] <=data[biggerIndex])
{
swap(data,i,biggerIndex);
}
}
}
public static void main(String args[])
{
int a[] = {5,3,8,4,6,7,2,1};
HeadSort as = new HeadSort();
as.headSort(a);
// int[] result = new HeadSort().headSort(a);
for(int i=0;i<a.length;i++)
{
System.out.println(a[i]);
}
}
}
}
用于从多个数中找出最大(小)的n个