Java实现堆排序

堆排序使用的是完全二叉树。 即满足r(n)的左孩子是r(2*n+1),右孩子是r(2*n+2)。

堆排序它首先将所有的元素添加到堆上,然后不断移除最大的元素并用最后一个叶子结点替换根节点之后再调整堆到大顶堆或者小顶堆的一种排序方法。底层是使用ArrayList进行存储元素的。

大顶堆的概念:即根节点是最大的(相对于左右孩子结点)元素 例如下面的图
在这里插入图片描述
小顶堆的概念:即根节点存储的是最小的(相对于左右孩子结点)元素 例如下面的图
在这里插入图片描述

大顶堆的排序示意图如下

示例数组int[] arr = {3,2,1,4,5}

  1. 首先使将数组存储到自己的构造的堆中。
    在这里插入图片描述
  2. 将根节点移除 并将末节点放到根节点的位置 并且重新开始调整堆
    picture
  3. 调整的过程
    在这里插入图片描述
  4. 如此循环
代码实现
  1. 构造堆类
class Heap<E extends Comparable<E>>{
    private ArrayList<E> list = new ArrayList<>();
    public Heap(){
    }
    //从数组添加
    public Heap(E[] object){
        for(int i=0;i<object.length;i++){
            add(object[i]);
        }
    }
    public void add(E newObject){
        list.add(newObject);
        int currentIndex = list.size()-1;
        while(currentIndex>0){
            int parentIndex = (currentIndex-1)/2;
            if(list.get(currentIndex).compareTo(list.get(parentIndex))>0){
                E temp= list.get(currentIndex);
                //将父亲的结点和自己的结点交换位置
                list.set(currentIndex,list.get(parentIndex));
                list.set(parentIndex,temp);
            }else{
                break;
            }
            currentIndex=parentIndex;
        }
    }

    //删除根节点之后重新排序
    public E remove(){
        if(list.size()==0) return null;
        E removedObject = list.get(0);//弹出栈顶元素
        list.set(0,list.get(list.size()-1));//将最后一个叶子结点换到栈顶
        list.remove(list.size()-1);//删除最后一个结点
        int currentIndex=0;
        //重新调整成大顶堆
        while(currentIndex<list.size()){
            int leftChildIndex = 2*currentIndex+1;//左孩子下标
            int rightChildIndex = 2*currentIndex+2;//右孩子下标
            if(leftChildIndex>=list.size()) break;//如果左孩子大于list的大小说明调整成功了。
            int maxIndex = leftChildIndex;//假设最大的孩子结点是左孩子结点。
            if(rightChildIndex<list.size()){//说明还在列表中
                if(list.get(maxIndex).compareTo(list.get(rightChildIndex))<0){//比较左右结点哪个大
                    maxIndex= rightChildIndex;
                }
            }
            if(list.get(currentIndex).compareTo(list.get(maxIndex))<0) {//最大的结点和堆的根节点进行比较
                E temp = list.get(maxIndex);
                list.set(maxIndex, list.get(currentIndex));
                list.set(currentIndex, temp);
                currentIndex = maxIndex;//切换当点的结点
            }else{
                break;
            }
        }
        return removedObject;//返回头结点
    }
}
堆排序
public class HeapSort {
    //堆排序
    public static <E extends Comparable<E>> void  heapsort(E[] list){
        Heap<E> heap = new Heap<>();
        for(int i=0;i<list.length;i++){
            heap.add(list[i]);
        }
        for(int i=0;i<list.length;i++){
            list[i]=heap.remove();
        }
    }
    public static void main(String[] args) {
        Integer[] array= {2,1,3,5,7,4,2,-1,2,3,4};//大顶堆
        heapsort(array);
        for(int i=0;i<array.length;i++){
            System.out.print(array[i]+" ");
        }
    }
}

结果
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值