排序
概念
-
1.1 排序
排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
平时的上下文中,如果提到排序,通常指的是排升序(非降序)。
通常意义上的排序,都是指的原地排序(in place sort)。 -
1.2 稳定性
两个相等的数据,如果经过排序后,排序算法能保证其相对位置不发生变化,则我们称该算法是具备稳定性的排序
算法。9 , 5 , 2 , 7 , 12 , 2 , 4 , 6 , 9 , 23
排序后
前面的 2 依旧在后面的 2 的前面那么称这个算法具有稳定性
堆排序
其基本思想其实就是选择排序,只是寻求最大值的方式不同。选择排序是通过遍历求最大值(最小值),而堆排序是通过大顶堆和小顶堆的特性寻求最大值的,不需要数据移动,效率更高效一些。抽象起来是对堆的操作,也就是完全二叉树,所以时间复杂度为O(nlogn)。
我们可以用顺序存储数组表示堆。其中的关系为:当前元素下标的左孩子=当前元素下标 * 2 + 1,那么右孩子就是左孩子 + 1。
堆首元素就是0号下标对应的元素。所以只需要交换0号下标的元素到末尾即可。
注意的地方:交换完元素后,堆的特性可能就被破环了,所以当交换完成后一定要对改变后的堆进行调整(这里我才用的是向下调整)
所以我们的第一步就是建堆(建堆需要用到堆的调整方法见下文):
package 排序;
public class 堆排序 {
/**
* 调整大堆的方法,自顶向下调整
* @param i 表示要调整的局部堆的根节点的下标表示
* @param arr 待调整的数组(即堆)
* @param length length表示数组的长度(堆的元素个数)
*/
//注意:该方法是调整堆,前提arr数组是堆(只要i位置的元素不满足堆的性质),
//我们可以通过该方法调整i下标的元素的位置,让堆满足堆的定义
public static void adjustHeap(int i,int[] arr,int length){
//k则是i的左孩子的下标,k = i*2+1表示下一步的调整从k的左孩子开始
for(int k = i * 2 + 1;k < length;k = i * 2 +1){
if(k+1 < length && arr[k] < arr[k+1]){
//先将k移动到左右孩子中大的一方
k = k + 1;
}
if(arr[i] < arr[k]){
//之后再比较父子节点的大小
arr[i] = arr[i] ^ arr[k];
arr[k] = arr[i] ^ arr[k];
arr[i] = arr[i] ^ arr[k];
//这里有一个回溯,就是当上层的节点将小的数换下来后,会重新调整下面的子堆
i = k; //将父节点的下标移动到子节点,因为经过交换后可能子节点的堆不满足堆的给定义了
}else{
//说明调整完毕了
break;
}
}
}
/**
* 堆排序
* 思路:1.将数组调整为大顶堆,然后将最大的元素放到数组的最后
* 2.将数组前length-1数再调整为大顶堆,将次大的数放在数组的倒数第二个位置
* 3.重复类似的操作
* @param arr 待排序的数组
*/
public static void heapSort(int[] arr){
//1.首先我们将arr调整为大顶堆,自底向上
for (int i = arr.length / 2 -1; i >= 0 ; i--) {
adjustHeap(i,arr,arr.length);
}
for (int i : arr) {
System.out.println(i+" ");
}
//i是按堆的结构来说,从底向上的第一个非叶子节点
for(int i = arr.length -1;i > 0;i--){
//2.交换到后面
arr[0] = arr[0] ^ arr[i];
arr[i] = arr[0] ^ arr[i];
arr[0] = arr[0] ^ arr[i];
//将交换上去的小值调整下来
adjustHeap(0,arr,i);
}
}
public static void main(String[] args) {
int[] arr = {9,7,6,4,2,45,75,23,21};
heapSort(arr);
// adjustHeap(2,arr,arr.length);
for (int i : arr) {
System.out.println(i+" ");
}
}
}
总结:
堆排序是不稳定的,在堆的调整过程中非常容易将元素的相对位置改变。
注意:排升序建大堆,排降序建小堆(都是与最后的元素交换)
大堆将大的元素交换到最后最后形成的数组就是升序!
反之,小堆将小的元素交换到后面,最后形成的数组就是降序的!
注:如有运行错误,请评论一下我尽快更改,谢谢啦!