*最大堆建堆过程的优化
*与上条博客区别在于构造函数,heapify过程,具体来说:
public class MaxHeap {
private int count; //记录堆中存储元素的个数
private static int[] data; //用数组存储二叉堆
private int capacity;
//***********************
//heapify过程
//新建一个构造函数
public MaxHeap(int[]arr,int n) {
//data索引从1开始
data=new int[n+1];
for(int i=0;i<n;i++) {
data[i+1]=arr[i];
}
count=n;
// i=count/2,data数组中第一个不是叶子的节点
//叶子节点看成满足堆
//根节点从1开始
//此时构造方法已经实现了一个堆,不需要shiftUp,但是不能插入
for(int i=count/2;i>=1;i--) {
shiftDown(i);
}
}
//*****************************************
//判断堆是否为空
boolean isEmpty() {
return count==0;
}
//输出堆中元素个数
int size() {
return count;
}
public int getCapacity() {
return this.capacity;
}
//从堆中取出元素,优先队列思想
public int extractMax() {
if(count<=0)
return 0;
//先取出最大的(优先级高的)
int max=data[1];
//将堆中最后一个元素存入第一元素的位置
swap(1, count);
count--;
//将第一个元素向下移,找到合适位置,维护堆
shiftDown(1);
return max;
}
private void shiftDown(int i) {
//定义左孩子,完全二叉树如果有孩子,一定有左孩子
while (2*i<=count) {
int j=2*i;
//j+1即为右孩子
if(j+1<=count&&data[j+1]>data[j])
j+=1;
if(data[i]>=data[j])
break;
swap(i, j);
i=j;
}
}
private void swap(int i, int j) {
if(i!=j) {
int temp=data[i];
data[i]=data[j];
data[j]=temp;
}
}
public void print(int []data,int count) {
for(int i=0;i<=count;i++)
System.out.print(data[i]+" ");
System.out.println();
}
}
*第二种堆排序
*时间复杂度和空间复杂度均为O(n)
*第一种是将n个元素逐个插入到一个空堆中,所以为O(nlogn)
*优化方式只利用shiftDown,为O(n)
public class HeapSort1 {
public void heapSort2(int[]arr,int n) {
//此时已经实现一个堆,heapify过程
MaxHeap heap2=new MaxHeap(arr,n);
//从小到大排序
for(int i=n-1;i>=0;i--) {
arr[i]=heap2.extractMax();
}
}
public static void main(String[] args) {
int [] arr= {8,7,4,5,9,2,10,3,3,3,30,3};
int n=arr.length;
HeapSort1 sort2=new HeapSort1();
sort2.heapSort2(arr, n);
for(int i=0;i<n;i++)
System.out.print(arr[i]+" ");
}
}