算法原理
选择排序通过重复选择数组中最小元素,将其与未排序部分的第一个元素交换,实现排序。
算法描述
选择排序是一种简单的排序算法,它每次从待排序的元素中选择最小(或最大)的元素,将其放到已排序序列的末尾,直到整个序列排序完成。
选择排序的基本思想是通过不断选择剩余元素中的最小(或最大)元素,将其放置到已排序序列的末尾,从而逐步构建有序序列。具体步骤如下:
- 遍历待排序序列,找到最小(或最大)的元素。
- 将最小(或最大)元素与待排序序列的第一个元素交换位置,将该元素放置到已排序序列的末尾。
- 缩小待排序序列的范围,将已排序序列的长度增加1。
- 重复步骤1-3,直到待排序序列为空。
动画演示
代码实现
public void selectSort(int arr[]) {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
//交换 arr[i]和arr[minIndex]
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
算法复杂度
时间复杂度(最坏) | 时间复杂度(最好) | 时间复杂度(平均) | 空间复杂度 | 稳定性 |
---|---|---|---|---|
O(n^2) | O(n^2) | O(n^2) | O(1) | 不稳定 |
选择排序的优化方式:
- 设置一个标志位,记录每一趟遍历中最小(或最大)元素的位置,避免不必要的交换操作。
public void selectionSort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
if (minIndex != i) {
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
- 使用双指针,分别指向已排序序列的末尾和待排序序列的开头,减少交换操作的次数。
public void selectionSort(int[] arr) {
int n = arr.length;
int left = 0;
int right = n - 1;
//直到left和right指针相遇。
while (left < right) {
int minIndex = left;
int maxIndex = left;
//寻找最小和最大元素下标
for (int i = left + 1; i <= right; i++) {
if (arr[i] < arr[minIndex]) {
minIndex = i;
}
if (arr[i] > arr[maxIndex]) {
maxIndex = i;
}
}
//如果最小元素的位置不等于left,则将最小元素与已排序序列的末尾元素交换位置。
//此处的末尾是数值越来越大:1 3 4 ...
if (minIndex != left) {
int temp = arr[left];
arr[left] = arr[minIndex];
arr[minIndex] = temp;
}
//如果最大元素的位置等于left,则将最大元素的位置更新为最小元素的位置。
//因为上一步已经把最大元素换到了最小元素位置,所以需要重新设置下标
if (maxIndex == left) {
maxIndex = minIndex;
}
//如果最大元素的位置不等于right,则将最大元素与待排序序列的开头元素交换位置。
//此处的开头是数值越来越小:... 5 6 9
if (maxIndex != right) {
int temp = arr[right];
arr[right] = arr[maxIndex];
arr[maxIndex] = temp;
}
left++;
right--;
}
}
通过使用双指针的优化方式,可以减少交换操作的次数。在每一趟遍历中,同时找到最小元素和最大元素的位置,并根据情况进行交换操作。这样可以减少不必要的交换操作,提高排序的效率。同时,由于每一趟遍历中的交换操作次数减少,也减少了数据的移动次数,进一步提高了排序的效率。
相关概念
• 稳定
:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
• 不稳定
:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
• 时间复杂度
:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
• 空间复杂度
:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。