选择排序:简单选择排序、堆排序(改进)
改进思想:找到最大值的同时,找出较大值
1、基本思想
利用最大堆,最小堆的思想,分为两个过程:构建堆,交换堆顶元素和租后一个元素的位置
2、堆的定义
堆是具有下列性质的完全二叉树:每个结点的值都小于或等于其左右孩子结点的值(称为最小堆),或每个结点的值都大于或等于其左右孩子结点的值(称为最大堆)。
3、实现步骤
- 建立最大堆:遍历每个非叶结点来调整堆,如果其孩子结点大于父结点,则将孩子结点中的最大值和父结点交换,遍历完后得到的根即为最大值
- 将根节点的值和最后一个结点的值作交换,最后一个结点即位1~n个元素的最大值,接下来对1~n-1的结点做调整堆和交换操作,直到只剩下一个元素位置
4、代码实现
public
void
heapSort(
int[]
array){
//遍历每个非叶结点建立堆,从下往上遍历
int
len
=
array.
length;
for(
int
i
=(
len
-2)/
2;
i
>=
0;
i
--)
shifDown(
i,
len
-1,
array);
//并调整剩余的n-1个元素
for(
int
i
=
len
-1;
i
>=
0;
i
--){
swap(
0,
i,
array);
//交换根和最后一个元素的值
shiftDown(
0,
i
-1,
array);
//从上往下调整堆
}
}
//交换
private
void
swap(
int
i,
int
j,
int[]
array){
int
temp
=
array[
i];
array[
i]
=
array[
j];
array[
j]
=
temp;
}
//调整堆
private
void
shiftDown(
int
low,
int
high,
int[]
array){
int
root
=
low;
int
child
=
2
*
root
+1;
//root的左孩子
int
temp
=
array[
root];
while(
child
<=
high){
//让child指向孩子中最大的结点
if(
child
<
high
&&
array[
child]
<
array[
child
+1])
child
++;
//如果根大于或等于孩子中最大的结点,则跳出循环
if(
temp
>=
array[
child])
break;
//否则交换根与孩子中的最大结点值,让根指向child,child指向其左孩子
array[
root]
=
array[
child];
root
=
child;
child
=
2
*
child
+1;
}
array[
root]
=
temp;
}
5、时间复杂度
建堆的过程时间复杂度O(n),调整堆的过程时间复杂度O(nlogn),那么T(n) = O(nlogn)
6、空间复杂度
临时元素temp的使用,O(1)
7、稳定性:不稳定