堆排序
每次将堆顶元素取出,与末尾元素交换,调整前n-1个元素,使其仍然成堆,重复上述过程,直到剩余元素为1时为止,即可得到非递减序列
- 最大堆的堆顶时整个堆中的最大元素
- 最小堆的堆顶时整个堆中的最小元素
代码演示
public static void downAdjust(int [] array,int parentIndex,int length){ //temp保存父节点值,用于最后的赋值 int temp=array[parentIndex]; int childIndex=2*parentIndex+1; while(childIndex<length){ //如果有右孩子,且右孩子大于左孩子的值,则定位到右孩子 if (childIndex+1<length && array[childIndex+1]>array[childIndex]){ childIndex++; } //如果父节点大于任何一个孩子的值,则直接跳出 if (temp>=array[childIndex]) break; //无须真正交换,单项赋值即可 array[parentIndex]=array[childIndex]; parentIndex=childIndex; childIndex=2*childIndex+1; } array[parentIndex]=temp; } /** * 堆排序(升序) * @param array 待调整的堆 */ public static void heapSort(int[] array){ //1.把无序数组构建成最大堆 for (int i = (array.length-2)/2; i >=0 ; i--) { downAdjust(array,i,array.length); } //2. 循环删除堆顶元素,移到集合尾部,调整堆产生的新的堆顶 for (int i = array.length-1; i >0 ; i--) { //最后一个元素和第一个元素进行交换 int temp=array[i]; array[i]=array[0]; array[0]=temp; //"下沉"调整最大堆 downAdjust(array,0,i); } } public static void main(String[] args) { int arr[]={4,4,6,5,3,2,8,1,9,3,5,6,7,12,23,34,21,22,14,19}; heapSort(arr); System.out.println(Arrays.toString(arr)); }
时间复杂度:
堆排序平均性能接近于最坏性能,时间复杂度为O(nlog2 n)
空间复杂度:
仅用arr[0]作为交换辅助空间,空间复杂度为O(1)
算法特点:
1、不稳定排序
2、只能用于顺序结构,不能用于链式结构
3、初始建堆所需要的比较次数比较多,记录较少时不宜采用,堆排序在最坏情况下的时间复杂度为O(nlog2 n),相对于快速排序最坏情况下的O(n^2)而言是个优点,当记录较多时较为高效。