选择排序分两种-直接选择排序和堆排序
直接选择排序
算法思想:第一趟从n个元素中选出关键字最小/大的元素并放在最前/后的位置,依次类推,经过n-1趟完成排序
private static void selectSort(int[] keys) {
for (int i = 0; i < keys.length-1; i++) {
int min = i;//用来记录最小元素的角标
for (int j = i+1; j < keys.length; j++) {
if (keys[j]<keys[min]) {
min = j;//如果j角标对应的的更小,j赋值给min
}
if (min!=i) {//经过调换
int temp = keys[min];
keys[min] = keys[i];
keys[i] = temp;
}
}
}
}
- 直接选择排序比较次数与初始排列无关,第i趟排序的比较次数是n-i;
- 移动次数与初始排序有关,可能移动0次,也可能移动3(n-1)次。
- 算法总比较次数是1+2+3+…+(n-1)=(n-1+1)(n-1)/2≈n2/2。时间复杂度是O(n2)
- 空间复杂度是O(1)。
- 直接选择排序算法是不稳定的
堆排序
利用完全二叉树特性的一种选择排序
private static void heapSort(int[] keys) {
for (int i = keys.length/2-1; i >=0; i--) {
sift(keys,i,keys.length-1);
}
for (int i = keys.length-1; i > 0 ; i--) {
int temp = keys[0];
keys[0] = keys[i];
keys[i] = temp;
sift(keys, 0,i-1);
}
}
private static void sift(int[] keys, int parent, int end) {
int child = 2*parent+1;//child是parent的左孩子
int value = keys[parent];//最后一个节点的父亲节点的值
while (child<=end) {//沿着较小值孩子节点往下筛选
if (child<end&&keys[child]>keys[child+1]) {//如果左子树大于右子树
child++;//此时child是数值比较小的那个的角标
}
if (value>keys[child]) {//如果父亲节点的值大于最小的那个孩子
keys[parent] = keys[child];//将较小的孩子上移,成为父亲
parent = child;//将parent、child都向下移动一层
child = 2*parent+1;
}
else
break;
}
keys[parent] = value;//当前子树的原根值调整后的位置
}
- 将一个数据调整为堆的时间复杂度是O(log2n),因此时间复杂度也是O(n*log2n)。
- 堆排序的空间复杂度是O(1)。
- 排序算法不稳定。
- 其他博客关于堆排序的讲解,谢谢原博主