1、什么是选择排序?
选择排序的原理:
选择排序在开始的时候,先扫描整个列表,以找到列表中的最小元素,然后将这个元素与第一个元素进行交换。这样最小元素就放到它的最终位置上。然后,从第二个元素开始扫描,找到n-1个元素中的最小元素,然后再与第二个元素进行交换。以此类推,直到第n-1个元素(如果前n-1个元素都已在最终位置,则最后一个元素也将在最终位置上)。选择排序的基本思想是:
每一趟在n − i + 1 ( i = 1 , 2 , . . . , n − 1 ) 个元素中选择最小的元素,并将其作为有序序列中第 i 个元素。
2、选择排序的图示:
3、选择排序的分类
常见的选择排序可以分为直接选择排序(Straight selection sort)、树形选择排序(Tree-type selection sort)以及堆排序(Heap sort)。
(1)直接选择排序。基本思想:实现思想是每步从排序记录中选出排序码最小(最大)的记录,放在已排序记录序列的最后(前)
(2)树形选择排序。基本思想:其实现思想是保存先前比较的结果以减少比较次数,是一种不稳定的排序方法。首先对n个记录的关键字进行两两比较,然后在n/2个较小者之间再进行两两比较,如此重复,直至选出最小的记录为止。
(3)堆排序。基本思想:堆排序是一种树形选择排序,是对直接选择排序的有效改进。
4、直接选择排序
算法分析:
初始状态:无序区为R[1…n],有序区为空;
第i趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为R[1…i-1]和R(i…n)。该趟排序从当前无序区中-选出关键字最小的记录R[k],将它与无序区的第1个记录R交换,使R[1…i]和R[i+1…n)分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区;
经过n-1趟结束,使数组有序化了。
代码实现:
void select(int[] array){
int len = array.length;
int minIndex;
for(int i = 0; i < array.length; i++){
minIndex = i;
for(int j = i+1; j<len; j++){
if(array[j] < array[minIndex]){
minIndex = j;
}
}
if(minIndex != i){
int temp=array[minIndex];
array[minIndex]=array[i];
array[i]=temp;
}
}
}
时间复杂度:最好和最坏都是O(n2);
eg:对{4,6,8,7,9,2,10,1}进行排序
第一轮:1,6,8,7,9,2,10,4
第二轮:1,2,8,7,9,6,10,4
第三轮:1,2,4,7,9,6,10,8
第四轮:1,2,4,6,9,7,10,8
第五轮:1,2,4,6,7,9,10,8
第六轮:1,2,4,6,7,8,10,9
第七轮:1,2,4,6,7,8,9,10
排序完成。
5、树形选择排序
树形选择排序也叫竞标赛排序,是一种按照锦标赛的思想进行选择的排序方法,该方法是在简单选择排序方法上的改进。简单选择排序,花费的时间大部分都浪费在值的比较上面,而锦标赛排序刚好用树保存了前面比较的结果,下一次比较时直接利用前面比较的结果,这样就大大减少比较的时间,从而降低了时间复杂度,由O(n^2)降到O(nlogn),但是浪费了比较多的空间,“最大的值”也比较了多次。
图示如下:
6、堆排序
什么是堆:堆是一种叫做完全二叉树的数据结构,可以分为大根堆,小根堆,而堆排序就是基于这种结构而产生的一种程序算法。
大根堆:每个节点的值都大于或者等于他的左右孩子节点的值
小根堆:每个结点的值都小于或等于其左孩子和右孩子结点的值
排序思想:
1.首先将待排序的数组构造成一个大根堆,此时,整个数组的最大值就是堆结构的顶端
2.将顶端的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数组个数为n-1
3.将剩余的n-1个数再构造成大根堆,再将顶端数与n-1位置的数交换,如此反复执行,便能得到有序数组(升序用大根堆,降序用小根堆)
小根堆的构建:
对于一组无序数组{49,38,65,97,76,13,27,49}
基本步骤:
1. 把无序数组构建成二叉堆。
2. 循环删除堆顶元素,移到集合尾部,调节堆产生新的堆顶。
堆排序是不稳定的排序,空间复杂度为O(1),平均的时间复杂度为O(nlogn),最坏情况下也稳定在O(nlogn)