堆排序,Java实现

这里用数组实现一个堆排序,其他排序算法可见我的其他博文。


第一个类:Heap.java,建立大顶堆,即堆顶的元素每次都是堆中最大的数。

import java.util.ArrayList;

/**
 * 用数组实现一个大顶堆,小顶堆类似
 * 时间复杂度:O(nlogn)
 * 空间复杂度比归并排序要好
 * @param <E>
 */
public class Heap<E extends Comparable<E>>{
    //用于建立堆的数组
    private ArrayList<E> list;
    //空参构造方法,规范
    public Heap(){}
    //传入需要排序的数组,进行堆的构造
    public Heap(E[] objects){
        //直接定义数组最终大小,防止扩容带来的额外时间消耗
        list = new ArrayList<>(objects.length);
        //遍历要排序的数组,依次存入堆中,进行排序
        for (int i = 0; i < objects.length; i++){
            add(objects[i]);
        }
    }

    /**
     * 添加元素的时候,先添加到数组最后,然后不断跟父亲比较,
     * 若当前元素比父亲大则与父亲交换位置,直至父亲元素大于当前元素值
     * @param newObject
     */
    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;
        }
    }

    /**
     * 把最后一个元素替换到堆顶,然后跟左右子元素比较获取最大那个,替换位置
     * 直到左右子元素都比当前元素小
     * @return
     */
    public E remove(){
        //堆是空的,返回
        if (list.size() == 0){
            return null;
        }
        //获取堆顶元素返回
        E removiedObject = 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;
            }
            //当存在子元素
            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 removiedObject;

    }

    public int getSize(){
        return list.size();
    }
}

第二个类:HeapSort.java,测试堆排序


public class HeapSort {
    /**
     * 传入需要排序的数组.返回排序完成的数组
     * @param list
     * @param <E>
     */
    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[] list = {-23, -34, 1, 23, 0, 12, 53, 2, 1, 23, -10};
        //使用堆排序
        heapSort(list);
        //输出排序结果
        for (int i = 0; i < list.length; i++){
            System.out.print(list[i] + "  ");
        }
    }
}

猜你喜欢

转载自blog.csdn.net/aa792978017/article/details/89075410
今日推荐