数组和链表、选择排序
* <第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));
}
}