Java实现堆排序

匆匆过客 提交于 2020-01-24 22:16:18

堆排序使用的是完全二叉树。 即满足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]+" ");
        }
    }
}

结果
在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!