1、选择排序(Selection Sort)
1.1 算法描述
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
1.2 动画演示
1.3 代码实现
package sort;
//平均时间复杂度:O(n²) 最好:O(n²) 最坏:O(n²) 空间复杂度:O(1) 不稳定
public class SelectSort {
public static void main(String[] args) {
int[] arr = { 4, 2, 0, 8, 5, 1, 3, 9, 6, 7 };
selectSort(arr);
print(arr);
}
public static void selectSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int minPos = i; // 每次都要找到未排序最小元素的下标
for (int j = i + 1; j < arr.length; j++) {
// minPos = arr[minPos] > arr[j] ? j : minPos;
if(arr[minPos] > arr[j])
minPos = j;
}
swap(arr, i, minPos);
}
}
static void swap(int[] arr, int i, int minPos) {
int temp = arr[i];
arr[i] = arr[minPos];
arr[minPos] = temp;
}
static void print(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
}
2、堆排序(Heap Sort)
2.1 算法描述
堆积是一个近似完全二叉树,满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
- 将初始待排序关键字序列构建成大顶堆,此堆为初始的无序区;
- 将堆顶元素与最后一个元素交换,此时得到新的无序区和新的有序区;
- 由于交换后新的堆顶可能违反堆的性质,因此需要对当前无序区调整为新堆,然后再次将堆顶与无序区最后一个元素交换,得到新的无序区和新的有序区。不断重复此过程直到有序区的元素个数为n-1,则整个排序过程完成。
2.2 动画演示
2.3 代码实现
package sort;
//结点的左子结点对应的数组2*n+1,右子结点2*n+2
//平均时间复杂度:O(nlogn) 最好:O(nlogn) 最坏:O(nlogn) 空间复杂度:O(1) 不稳定
public class HeapSort {
public static void main(String[] args) {
int[] arr = { 2, 4, 3, 5, 6, 7, 9, 1, 8 };
sort(arr);
System.out.println(Arrays.toString(arr));
}
/**
* 堆排序:
* 1、构建大顶堆
* 2、交换堆顶和末尾元素
* 3、继续构建大顶堆
*/
public static void sort(int[] arr) {
for (int i = arr.length / 2; i >= 0; i--) {
adjustHeap(arr, i, arr.length - 1);
}
for (int t = arr.length - 1; t > 0; t--) {
int temp = arr[t];
arr[t] = arr[0];
arr[0] = temp;
adjustHeap(arr, 0, t - 1);
}
}
// 将一个二叉树,调整成一个大顶堆
public static void adjustHeap(int[] arr, int s, int length) {
int temp = arr[s];
for (int j = s * 2 + 1; j < length; j = j * 2 + 1) {
if (j + 1 < length && arr[j] < arr[j + 1])
j++;
if (arr[j] <= temp)
break;
arr[s] = arr[j];
s = j;
}
arr[s] = temp;
}
}