目录
本文详细讲解了选择排序,有需求的伙伴可以观看。
一、直接选择排序
选择排序的思想:每一轮从待排序区间里选出最小(或最大)的元素,放到待排序区间的最前面,逐步缩小待排序区间。
步骤:
- 初始:已排序区为空,整个数组都是待排序区。
- 第 1 轮:在全部待排序元素中找到最小值的下标,和待排序区第一个元素交换,此时第一个位置排好(最小的数)。
- 第 2 轮:在剩下的待排序元素里继续找最小值,和待排序区第一个位置交换,前两个位置有序。
- 不断重复,待排序区间不断缩小,直到只剩 1 个元素,排序结束。
图例:

代码示例:
java
/**
* 直接选择排序
* Time complexity :O(N^2)
* Space complexity :O(1)
* Stability : unstable
* @param array
*/
public static void selectSort(int[] array){
for(int i = 0; i < array.length; i++){
int minIndex = i;
for(int j = i + 1; j < array.length; j++){
if(array[minIndex] > array[j]){
minIndex = j;
}
}
swap(array,i,minIndex);
}
}
public static void swap(int[] array,int i,int j ){
int tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
【直接选择排序的特性总结】
- 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
- 时间复杂度:O(N^2)
- 空间复杂度:O(1)
- 稳定性:不稳定
1)直接选择排序的优化
在上面这个选择排序中,只是将最小值的下标进行了交换,而优化后的可以同时对最小值和最大值的下标进行同时交换。
思想:
数组依然划分:[left ... right] 待排序区间
- 在 left
~ right里同时找到最小值下标 minIdx、最大值下标 maxIdx - 把最小值交换到 low 位置
- 把最大值交换到 high 位置
- left++,right--,缩小区间,直到 left >= right
坑点:如果最大值下标刚好等于 low(最小值原来在 max 的位置,交换 min 之后 max 的位置变了!),要特殊处理
下面是图例:

代码示例:
java
public static void selectSort2(int[] array){
int left = 0;
int right = array.length - 1;
while(left < right){
int minIndex = left;
int maxIndex = left;
for(int i = left + 1; i <= right;i++){
if(array[i] > array[maxIndex]){
maxIndex = i;
}
if (array[i] < array[minIndex]) {
minIndex = i;
}
}
swap(array,left,minIndex);
if(maxIndex == left){
maxIndex = minIndex;
}
swap(array,right,maxIndex);
left++;
right--;
}
}
二、堆排序(从小到大排序)
思路:堆排序需要我们先建大根堆,此时堆顶的元素一定是最大值,使堆顶的元素和最后一个元素的位置进行交换,此时最大值就跑到最后面了,这个时候我们再把有效长度减一,从堆顶继续向下调整重复这个操作。
图例:


代码示例:
java
public static void heapSort(int[] array){
createHeap(array);
int end = array.length - 1;
while(end > 0){
swap(array,0,end);
shiftDown(array,0,end);
end--;
}
}
private static void createHeap(int[] array) {
for(int parent = (array.length - 1 -1) / 2; parent >= 0;parent--){
shiftDown(array,parent,array.length);
}
}
private static void shiftDown(int[] array, int parent, int length) {
int child = parent * 2 + 1;
while(child < length){
if(child + 1 < length &&array[child] <array[child + 1]){
child++;
}
if(array[child] > array[parent]){
swap(array,child,parent);
parent = child;
child = 2 * parent +1;
}else{
break;
}
}
}
public static void swap(int[] array,int i,int j ){
int tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
}
【堆排序的特性总结】
-
- 堆排序使用堆来选数,效率就高了很多。
-
- 时间复杂度:O(N*logN)
-
- 空间复杂度:O(1)
-
- 稳定性:不稳定