什么是堆???
可以把堆看成是一颗完全二叉树,并且这颗完全二叉树有一个特点:根节点比其左右叶子结点的值都大或者都小。如果每一个根节点比其左右叶子节点的值都大,则称之为大顶堆,反之就称为小顶堆。这一规则必须在完全二叉树的任一子树都满足。
完全二叉树的特点:设根节点的索引值为index;
(1)左节点的索引值为 2indexe +1;
(2)右节点的索引值为 2index+2;
(3)其父节点的值为(index-1)/2;
//构造小顶堆
public static void minHeap(int[] data,int size,int index)
{
//左子节点
int leftNode = 2*index+1;
//右子节点
int rightNode = 2*index+2;
int max = index;
//和两个子节点分别对比,找出最大的节点
if(leftNode < size&&data[leftNode] <data[max])
{
max = leftNode;
}
if(rightNode< size&&data[rightNode] < data[max])
{
max = rightNode;
}
//交换位置
if(max!=index)
{
int temp = data[index];
data[index] = data[max];
data[max] = temp;
//递归进行该节点子树小顶堆的创建
minHeap(data,size,max);
}
}
//构造完全的小顶堆
public static void BuildminHeap(int[] data)
{
int start = (data.length-1)/2;
for(int i = start; i >=0;i--)
{
minHeap(data,data.length,i);
}
}
//进行小顶堆排序
public static void minHeapSort(int[] data)
{
for(int i = data.length-1; i>0;i--)
{
int temp = data[0];
data[0] = data[i];
data[i] = temp;
minHeap(data, i, 0);
}
}
//构造大顶堆
public static void maxHeap(int[] data,int size,int index)
{
//左子节点
int leftNode = 2*index+1;
//右子节点
int rightNode = 2*index+2;
int max = index;
//和两个子节点分别对比,找出最大的节点
if(leftNode < size&&data[leftNode] >data[max])
{
max = leftNode;
}
if(rightNode< size&&data[rightNode] > data[max])
{
max = rightNode;
}
//交换位置
if(max!=index)
{
int temp = data[index];
data[index] = data[max];
data[max] = temp;
maxHeap(data,size,max);
}
}
//构造完全的大顶堆
public static void BuileMaxHeap(int[] data)
{
int start = (data.length-1)/2;
for(int i = start; i >=0;i--)
{
maxHeap(data,data.length,i);
}
}
//进行大顶堆排序
public static void maxHeapSort(int[] data)
{
for(int i = data.length-1; i>0;i--)
{
int temp = data[0];
data[0] = data[i];
data[i] = temp;
maxHeap(data, i, 0);
}
}
利用以上的知识,实现从数以百万计的数据中获取最大的前10个数字或者任意数量的最大数字,经测试1000000个数字耗时4毫秒。思想就是:先创建存有一定数字的小顶堆,根据小顶堆的性质,最小的数字位于根节点,因此后面来的数字只需与根节点相比较,比根节点大就进行交换,然后重新构造小顶堆,比根节点小则继续向后寻找。
public static int[] GetMaxNumber(int count, int[] data)
{
int[] maxNumber = new int[count];
//先取10个数字放入data中
for(int i =0; i < count; i++)
{
maxNumber[i] = data[i];
}
//构造小顶堆
BuildminHeap(maxNumber);
//获取data中count以后的数字,与maxNumber中的第一个元素进行比较,比第一个元素大就交换,重新构建小顶堆
for(int j = count;j < data.length; j++)
{
if(data[j] > maxNumber[0])
{
maxNumber[0] = data[j];
BuildminHeap(maxNumber);
}
}
return maxNumber;
}