算法图解(二):选择排序

数组和链表、选择排序

 * <第2章> 选择排序 </第2章>
 *  2.2 数组和链表
 *   2.2.1 链表
 *    (1)链表中的元素可存储在内存的任何地方
 *    (2)链表的每个元素都存储了下一个元素的地址,从而使一系列随机的内存地址串在一起
 *    (3)在链表中添加元素很容易:只需将其放入内存,并将其地址存储到前一个元素中
 *    (4)使用链表时,根本就不需要移动元素
 *    问题:
 *    (1)在需要读取链表的最后一个元素(或跳跃元素)时,不能直接读取,因为不知道它所处的地址,必须先访问元素#1,从中获取元素#2的地址,再访问元素#2并从中获取元素#3的地址,
 *     以此类推,直到访问最后一个元素。效率低
 *    (2)需要同时读取所有元素时,链表的效率很高:你读取第一个元素,根据其中的地址再读取第二个元素,以此类推
 *   2.2.2 数组
 *    (1)知道其中每个元素的地址,能做到顺序访问,随机访问,效率高;链表只能顺序访问
 *   2.2.3 常见的数组和链表操作运行时间
 *    (1)数组:读取 O(1)、插入 O(n)、删除 O(n)
 *    (2)链表:读取 O(n)、插入 O(1)、删除 O(1):仅当能够立即访问要删除的元素时,删除操作的运行时间才为O(1),比如第一个元素和最后一个元素
 *  2.3 选择排序 示例:{@link SelectionSort}
 *    (1)随着排序的进行,每次需要检查的元素数在逐渐减少,最后一次需要检查的元素都只有一个
 *    (2)并非每次都需要检查n个元素。第一次需要检查n个元素,但随后检查的元素数依次为n-1,n–2,...,2和1。平均每次检查的元素数为1/2 × n,因此运行时间为O(n × 1/2 × n)。
 *    但大O表示法省略诸如1/2这样的常数,因此简单地写作O(n × n)或O(n²)
 *  2.4 小结
 *    (1)计算机内存犹如一大堆抽屉
 *    (2)需要存储多个元素时,可使用数组或链表
 *    (3)数组的元素都在一起
 *    (4)链表的元素是分开的,其中每个元素都存储了下一个元素的地址
 *    (5)数组的读取速度很快
 *    (6)链表的插入和删除速度很快
 *    (7)在同一个数组中,所有元素的类型都必须相同(都为int、double等)
/**
 * 选择排序
 */
public class SelectionSort {

    /**
     * 找到数组中最小元素的索引
     *
     * @param arr
     * @return
     */
    private static int findSmallest(int[] arr) {
        // 存储最小的值
        int smallest = arr[0];
        // 存储最小元素的索引
        int smallestIndex = 0;
        // 遍历数组
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] < smallest) {
                smallest = arr[i];
                smallestIndex = i;
            }
        }

        return smallestIndex;
    }

    /**
     * 获取新的数组,排除索引为index的元素
     *
     * @param arr
     * @param index
     * @return
     */
    private static int[] getNewArr(int[] arr, int index) {
        if (arr.length == 1) {
            return arr;
        }
        // 每次去除一个元素的新数组
        int[] newArr = new int[arr.length - 1];
        int k = 0;
        for (int j = 0; j < arr.length; j++) {
            if (j != index) {
                newArr[k] = arr[j];
                k++;
            }
        }

        return newArr;
    }

    /**
     * 选择排序
     *
     * @param arr
     * @param newArr
     * @param i
     */
    private static void selectionSort(int[] arr, int[] newArr, int i) {
        if (arr.length > 1) { //递归条件
            // 找出数组中最小的元素,并添加到新数组中
            int smallestIndex = findSmallest(arr);
            newArr[i] = arr[smallestIndex];
            i++;
            // 递归调用
            selectionSort(getNewArr(arr, smallestIndex), newArr, i);
        } else if (arr.length == 1) { // 基线条件
            // 最后一个元素,就是最大的,直接放在新数组最后一位
            newArr[i] = arr[arr.length - 1];
        }
    }

    public static void main(String[] args) {
        int[] arr = {1, 4, 6, 2, 33, 45, 22, 87, 45, 67};
        int[] newArr = new int[arr.length];
        int i = 0;

        selectionSort(arr, newArr, i);
        System.out.println(Arrays.toString(newArr));
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值