选择排序——直接选择与堆排序

选择排序:通过每次选择出待排序列中的最大值或最小值,并将其移除队列,输出到新的已排序列。逐步执行,直到选出待排序列中最后一个元素,则输出结果即为排好序的最终结果。

直接选择排序

直接选择排序,通过每次遍历待排序列中的元素,选择出其中最大或最小元素值,将它与其应在位置的元素进行交换,因此确定了该元素对应的位置。外层循环从序列某端开始,遍历要确定的位置,嵌套执行后

动态演示图如下:
直接选择排序
代码实现如下:

import java.util.Arrays;

/**
 * @description: select sort method
 * @author: liyaguang
 * @create: 2018-12-03 13:26
 **/
public class SelectSort {
    
    public static void main(String[] args){

        int[] arrOriginal = new int[]{5, 9, 7, 4, 22, 2, 65, 1, 45};
        System.out.println("before select sort, the array is: ");
        System.out.println(Arrays.toString(arrOriginal));

        // 最小元素下标存放临时变量
        int smallestIdx;
        // 每次待确定值的索引位置
        for (int i = 0; i < arrOriginal.length - 1; i++) {
            smallestIdx = i;

            // 遍历待排序序列,选出其中最小元素
            for (int j = i+1; j < arrOriginal.length; j++) {
                if (arrOriginal[j] < arrOriginal[smallestIdx]) {
                    smallestIdx = j;
                }
            }
            
            // 将最小值移动到它对应的索引位置
            Utils.switchVal(arrOriginal, i, smallestIdx);
        }
        System.out.println("\nend select sort, the array is: ");
        System.out.println(Arrays.toString(arrOriginal));
    }
}

直接插入排序的时间复杂度为O(n2)。

堆排序

堆排序:在直接选择排序的思想上,利用这种数据结构的特点,可以直接选择得出最大或最小元素。堆是一种特殊的完全二叉树,分为最大堆或最小堆,最大堆的父节点值>=两个子节点值,最小堆的父节点值<=两个子节点值。后来堆的含义被引申为程序设计语言中的垃圾收集区域。

算法主要的关键是构建出堆这种数据结构,下文演示了通过使用最大堆进行堆排序的代码。其中最大堆数据结构通过数组来实现,最大堆的元素个数要小于等于数组元素个数,用Heap类对象中的heapSize属性表示

动态演示图如下:
堆排序
代码实现如下:

  1. 最大堆数据结构的实现
/**
 * max heap data structure
 *
 * @author liyaguang
 */
public class Heap {
    private int heapSize;

    public int getHeapSize() {
        return heapSize;
    }

    public void setHeapSize(int size) {
        this.heapSize = size;
    }

    public int getParentIdx(int i) {
        return i / 2;
    }

    public int getLeftIdx(int i) {
        return 2 * i;
    }

    public int getRightIdx(int i) {
        return 2 * i + 1;
    }

    /**
     * 调整最大堆,使其符合数据结构要求
     *
     * @param arr 源数组
     * @param i   待调整元素在数组中的元素下标
     */
    public void maxHeapify(int[] arr, int i) {
        int left = getLeftIdx(i);
        int right = getRightIdx(i);
        int largest = i;
        if (left < heapSize && arr[left] > arr[largest]) {
            largest = left;
        }
        if (right < heapSize && arr[right] > arr[largest]) {
            largest = right;
        }
        if (largest != i) {
            Utils.switchVal(arr, i, largest);
            maxHeapify(arr, largest);
        }
    }

    /**
     * 构建最大堆
     *
     * @param arr 源数组
     */
    public void buildMaxHeap(int[] arr) {
        this.setHeapSize(arr.length);
        for (int i = (arr.length / 2); i >= 0; i--) {
            maxHeapify(arr, i);
        }
    }
}
  1. 基于最大堆数据结构实现的堆排序主要算法
import java.util.Arrays;

/**
 * heap sort algorithm
 *
 * @author liyaguang
 */
public class HeapSort {

    public static void main(String[] args) {

        int[] arr = new int[]{5, 9, 7, 4, 22, 2, 65, 1, 45};
        System.out.println("before select sort, the array is: ");
        System.out.println(Arrays.toString(arr));

        // 建最大堆
        Heap heap = new Heap();
        heap.buildMaxHeap(arr);

        // 选取堆顶最大元素,放置到数组对应位置后,调整最大堆
        for (int i = arr.length - 1; i > 0; i--) {
            Utils.switchVal(arr, i, 0);
            heap.setHeapSize(heap.getHeapSize() - 1);
            heap.maxHeapify(arr, 0);
        }

        System.out.println("\nend heap sort, the array is: ");
        System.out.println(Arrays.toString(arr));
    }

}

堆排序时间复杂度为:O(nlogn)

小结

通过每次选出最值的方式,直接选择排序采用的办法——遍历,而堆排序建立在已经有序的一种数据结构之上,而且,每次的选最值后,调整堆结构是建立在已经部分有序的基础上,少做了很多比较,提升了运行效率。

参考资料:
《算法导论》
Selection sort - wikiwand
Heapsort - wikiwand

该系列示例代码下载:欢迎关注我的github

发布了159 篇原创文章 · 获赞 225 · 访问量 21万+

猜你喜欢

转载自blog.csdn.net/lyg673770712/article/details/86707919