首先说明,这个堆排序是百度百科的JAVA实现版本,但是这个版本有几处错误,所以我在这里补充一下,下面贴上修改后的代码,标红色的就是修改后的地方
public class HeapSort {
private static int[] sort=new int[]{1,0,10,20,3,5,6,4,9,8,12,17,34,11};
//private static int[] sort=new int[]{1,2,3,4,5,6,9,7,21};
public static void main(String args[]){
buildMaxHeapify(sort);
heapSort(sort);
print(sort);
}
private static void buildMaxHeapify(int[] data){
int startIndex=getParentIndex(data.length-1);
for(int i=startIndex;i>=0;i--)
maxHeapify(data,data.length-1,i);
}
//创建最大堆
private static void maxHeapify(int[] data,int heapSize,int index){
int left=getChildLeftIndex(index);
int right=getChildRightIndex(index);
//倒数第二个数必须比倒数第一个大数据才正确,但是这里改成<=时候,前面数据正确,但是后面又出问题了
largest=left;
if(right<=heapSize&&data[largest]<data[right])
largest=right;
//得到最大值后可能需要先交换,如果交换不了,其子结点可能就不是最大堆了,需要重新调整
if(largest!=index){
int temp=data[index];
data[index]=data[largest];
data[largest]=temp;
maxHeapify(data,heapSize,largest);
}
System.out.println("--------------");
print(data);
System.out.println("--------------");
}
//排序,最大值放在末尾,data虽然是最大堆,在排序后就成了递增的
private static void heapSort(int[] data){
System.out.println("开始排序~~~~~~");
//末尾与头交换,交换后调整最大堆
for(int i=data.length-1;i>0;i--){
int temp=data[0];
data[0]=data[i];
}
}
private static int getParentIndex(int current){
return (current-1)>>1;
}
private static int getChildLeftIndex(int current){
return (current<<1)+1;
}
private static int getChildRightIndex(int current){
return (current<<1)+2;
}
private static void print(int[] data){
int pre=-2;
for(int i=0;i<data.length;i++){
if(pre<(int)getLog(i+1)){
pre=(int)getLog(i+1);
System.out.println();
}
System.out.println(data[i]+"|");
}
}
private static double getLog(double param){
return Math.log(param)/Math.log(2);
}
public class HeapSort {
private static int[] sort=new int[]{1,0,10,20,3,5,6,4,9,8,12,17,34,11};
//private static int[] sort=new int[]{1,2,3,4,5,6,9,7,21};
public static void main(String args[]){
buildMaxHeapify(sort);
heapSort(sort);
print(sort);
}
private static void buildMaxHeapify(int[] data){
int startIndex=getParentIndex(data.length-1);
for(int i=startIndex;i>=0;i--)
maxHeapify(data,data.length-1,i);
}
//创建最大堆
private static void maxHeapify(int[] data,int heapSize,int index){
int left=getChildLeftIndex(index);
int right=getChildRightIndex(index);
//倒数第二个数必须比倒数第一个大数据才正确,但是这里改成<=时候,前面数据正确,但是后面又出问题了
int largest=index;
//原本版是if(left<heapSize&&data[index]<data[left]),没有等于号
if(left<=heapSize&&data[index]<data[left])largest=left;
if(right<=heapSize&&data[largest]<data[right])
largest=right;
//得到最大值后可能需要先交换,如果交换不了,其子结点可能就不是最大堆了,需要重新调整
if(largest!=index){
int temp=data[index];
data[index]=data[largest];
data[largest]=temp;
maxHeapify(data,heapSize,largest);
}
System.out.println("--------------");
print(data);
System.out.println("--------------");
}
//排序,最大值放在末尾,data虽然是最大堆,在排序后就成了递增的
private static void heapSort(int[] data){
System.out.println("开始排序~~~~~~");
//末尾与头交换,交换后调整最大堆
for(int i=data.length-1;i>0;i--){
int temp=data[0];
data[0]=data[i];
data[i]=temp;
//原版本是maxHeapify(data,i,0);
maxHeapify(data,i-1,0);}
}
private static int getParentIndex(int current){
return (current-1)>>1;
}
private static int getChildLeftIndex(int current){
return (current<<1)+1;
}
private static int getChildRightIndex(int current){
return (current<<1)+2;
}
private static void print(int[] data){
int pre=-2;
for(int i=0;i<data.length;i++){
if(pre<(int)getLog(i+1)){
pre=(int)getLog(i+1);
System.out.println();
}
System.out.println(data[i]+"|");
}
}
private static double getLog(double param){
return Math.log(param)/Math.log(2);
}
}
首先原版本堆排序是错误的,只有倒数第一个不是最大的数的时候,原版本才是正确的。
因为没有等于号,所以每次判断,都没有判断最后一个元素。
此外,原版本是i,这样其实重复多执行了一次,所以修改成i-1,并且只有修改成i-1后,if(left<=heapSize&&data[index]<data[left])这条语句才算正确,否则就会错误地把最后一个元素也算进排序中,这样就排序出错了,可能解释的不太清楚,之后再详细修改。现在先就指出百度百科这两个错误的地方