简介
选择排序是一种常用的排序方法,其排序思想是这样的:对于数组n,第一趟排序取出n个元素中最小的元素,第二趟排序取出剩余n-1个元素中最小的元素……直到整个数组取完为止。常用的选择排序有简单选择排序、树形选择排序和堆排序。
注意:选择排序是一种不稳定的排序算法
一、简单选择排序
简单选择排序是一种比较好理解的选择排序,其实现思想也非常简单:对于数组n,第一趟排序找出n个元素中最小的元素与第1个元素交换,第二趟排序找出剩下的n-1个元素中最小的元素与第2个元素交换…直到整个序列有序,算法的时间复杂度为O(n2)。这种方法很简单,所以不做过多的解释。
二、树形选择排序
树形选择排序又称锦标赛排序,是一种按照锦标赛的思想进行选择排序的方法。首先对n个记录的关键字进行两两比较,然后在n/2个较小者之间再进行两两比较,如此重复,直至选出最小的记录为止。
树形选择排序的过程如下图所示:
时间复杂度是O(nlog2n)
三、堆排序
这里首先介绍一下堆这种结构,堆是满足下列这种要求的二叉树:任意一节点的值都大于等于(小于等于)其左右子节点的值。且分别称为最大堆、最小堆。
堆排序的过程:
①将n个元素建立成堆(这将用到下面的筛选②)
②筛选最大元素:第一趟将堆顶元素和nums[n-1]交换,并将nums[0]~nums[n-2]重建堆。第二趟将堆顶元素和nums[n-2]交换,并将nums[0]~nums[n-3]重建堆…直到排序完成。
堆排序的算法时间复杂度为O(nlog2n)
堆排序和快排的比较
由于堆排序最坏情况下的复杂度也为O(nlog2n),高于快排最坏情况下的O(n2),所以如果考虑到最坏情况,还是选择堆排序比较好。
附代码:
1.简单选择排序
class SelectSortTool{
public static void selectSort(int[] nums){
int temp;
int minuIndex;//找到的最小的数的下标
for(int i = 0 ;i < nums.length - 1; i ++){
minuIndex = i+1;
//搜索最小数的下标
for(int j = i + 1 ; j < nums.length ; j ++){
if(nums[j] < nums[minuIndex]){
minuIndex = j;
}
}
//交换
temp = nums[minuIndex];
nums[minuIndex] = nums[i];
nums[i] = temp;
}
}
}
2.堆排序
class HeapSortTool{
public static void HeapAdjust(int[] nums, int start, int last){
int temp ;
//调整从start到last之间的堆
for(int i = start ; i <= last ; i ++ ){
//调整以i为根的子树
if((2*i+2 <= last && nums[2*i+1] > nums[i] && nums[2*i+1] >= nums[2*i+2])||
(2*i+1 <= last && 2*i+2 > last && nums[2*i+1] > nums[i])){
//左右子节点都存在且左节点更大 或者 只有左子节点存在且更大
temp = nums[i];
nums[i] = nums[2*i+1];
nums[2*i+1] = temp;
}else if(2*i+2 <= last && nums[2*i+2] > nums[i] && nums[2*i+2] > nums[2*i+1]){
//右子节点更大
temp = nums[i];
nums[i] = nums[2*i+2];
nums[2*i+2] = temp;
}
if(i*2+1 > last)
break;
}
}
public static void HeapSort(int[] nums){
//建立堆
for(int i = nums.length/2 + 1; i >= 0 ; i --){
HeapAdjust(nums, i, nums.length-1);
}
int temp;
for(int i = nums.length-1 ; i > 0 ; i --){
temp = nums[0];
nums[0] = nums[i];
nums[i] = temp;
HeapAdjust(nums, 0, i-1);
}
}
}