简单选择排序---不稳定
选择排序在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后以此类推,直到所有元素均排序完毕。
for (int i = 0; i < arr.length; i++) {
//记录最小值下标位置
int min=i;
for (int j=i+1;j<arr.length;j++){
if (arr[i]>arr[j]){
min=j;
}
}
//交换位置
if (min != i) {
int tmp=arr[i];
arr[i]=arr[min];
arr[min]=tmp;//如果有两个相同的值,2,2,1,这种情况,第一次排序时,第一个2到了1的位置,所以排序不稳定
}
}
平均时间复杂度 | 最坏 | 最好 | 空间复杂度 |
---|---|---|---|
O(n²) | O(n²) | O(n²) | O(1) |
堆排序---不稳定
预备知识
1.父结点索引:(i-1)/2(这里计算机中的除以2,省略掉小数)
2.左孩子索引:2i+1
3.右孩子索引:2i+2
升序用大顶堆,降序用小顶堆。
//维护堆,参数为数组和当前需要维护的根节点,len表示堆中有多少元素
public void heapify(int[] arr,int len, int i) {
// 最大值节点
int max = i;
int lChild = i * 2 + 1;
int rChild = i * 2 + 2;
//找出孩子节点中最大的那个值,然后交换
if (lChild < len && arr[lChild] > arr[max]) {
max=lChild;
}
if (rChild < len && arr[rChild] > arr[max]) {
max=rChild;
}
//交换节点位置
if (max != i) {
swep(arr,i,max);
//递归维护之后的节点
heapify(arr,len,max);
}
}
//交换节点
public void swep(int[] arr,int i,int j){
int tmp=arr[i];
arr[i]=arr[j];
arr[j]=tmp;
}
//堆排序
public void heapSort(int[] arr) {
//建堆,i表示最后一个非叶子节点
for (int i = arr.length/2-1; i >=0; i--) {
heapify(arr,arr.length,i);
}
//排序,将堆顶元素和最后一个元素交换,然后将最后一个元素移除堆,维护堆,再将倒数第二个元素和堆顶元素交换......
for (int j = arr.length - 1; j >0 ; j--) {
swep(arr,j,0);
//最后一个元素不需要参与维护,所以长度是arr.length-1,一次减少一次
heapify(arr,j,0);
}
}
1.建立堆的过程, 从length/2 一直处理到0, 时间复杂度为O(n);
2.调整堆的过程是沿着堆的父子节点进行调整, 执行次数为堆的深度, 时间复杂度为O(lgn);
3.堆排序的过程由n次第2步完成, 时间复杂度为O(nlgn).
平均时间复杂度 | 最坏 | 最好 | 空间复杂度 |
---|---|---|---|
O(nlog2n) | O(nlog2n) | O(nlog2n) | O(1) |