堆排序算法java实现

16 篇文章 3 订阅
4 篇文章 1 订阅

概述

堆本质是完全二叉树的,只是在对二完全二叉树做了以下几个方面的限定:

1、大根堆:根结点大于等于其子结点的数据,左右子树大小没有限定,这样以来最大数据就是root结点

2、小根堆:根结点小于等于其子结点的数据,左右子树大小没有限定,这样以来最小的结点是root结点

3、堆排序的过程就是,取出根结点,重新构造堆(因为堆结构已破坏),取出根结点。。。。

4、对于任结点i 其中i[0,n-1],其左子树是2*i+1(要小于n),右子树2*i+1(要小于n),父结点是(n-1)/2,最后一个非叶结点是(n-1)/2或者n/2-1

下面结合代码做进一步讲解,不再提供图解说明,可自行去查阅!


public class HeapSort_1 {
static final int SIZE=10;
/**
* 用循环代替递归实现
* @param a
* @param length
*/
static public void heapSort(int a[],int length){
int i,j,h,k;
int t;
for(i=length/2-1;i>=0;i--){//初始化堆,对于完全二叉树,最后一个非叶结点是(length-1)/2或者length/2-1,从无序数据构造难是从最后一个非叶结点开始,向上进行构造
int m = i;//while中的变量不能用i,因为是向下调整,i会变化,所以只能新声明一个
while(2*m+1<length){//左子结点存在
j=2*m+1;
if(j+1 < length ){//j+1是右结点,判断是否存在,因为堆是完全二叉树,只有左子结点存在,右子结点才可能存在
if(a[j]<a[j+1]){//左右结点中大的与父结点比较即可
j++;
}
}
if(a[m] <a[j]){//父结点与左右子结点中大的比较,如果父结点小,交换数据
t=a[m];
a[m]=a[j];
a[j]=t;
m=j;//以j为根结点的子树被破坏,向下调整
}else{
break;//没有交换元素,以i为根点的子树,无需重建,继续调整i-1个结点
}
}
}//到此原始数据已构造成一个堆

System.out.println("原始数据构成的堆:");
for(h=0;h<length;h++){
System.out.print(" "+a[h]);
}

//这个for循环就是用来排序的,每次输出一个最大元素,然后调整堆
for(i=length-1;i>0;i--){
t=a[0];
a[0]=a[i];
a[i]=t; //此时a[i]最后一个元素,已排好序,下面重建堆的过程不再参与
k=0;
while(2*k+1<i){//i为剩余元素的个数,向下调整
j=2*k+1;
if(j+1 < i ){//j+1是右结点,判断是否存在,因为堆是完全二叉树,只有左子结点存在,右子结点才可能存在
if(a[j]<a[j+1]){//左右结点中大的与父结点比较即可
j++;
}
}
if(a[k] <a[j]){//父结点与左右子结点中大的比较,如果父结点小,交换数据
t=a[k];
a[k]=a[j];
a[j]=t;
k=j;//以j为根结点的子树被破坏,向下调整
}else{
break;//没有交换元素,以i为根点的子树,无需重建,继续调整i-1个结点
}
}
}
}
public static void main(String[] args) {
int[] a = new int[SIZE];
int i;
for(i=0;i<SIZE;i++){
a[i] = (int)(100+Math.random()*(100+1));
}
System.out.println("排序前的数据为: ");
for(i=0;i<SIZE;i++){
System.out.print(a[i]+" ");
}
System.out.println("");
heapSort(a, SIZE);
System.out.println("\n排序后的数据为: ");
for(i=0;i<SIZE;i++){
System.out.print(a[i]+" ");
}
}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿童木-atom

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值