堆排序原理与实现

    堆排序实际上是利用堆的性质来进行排序的,我们通常说的堆就是二叉堆,二叉堆又称完全二叉树或者近似完全二叉树。堆排序是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。数组可以根据索引直接获取元素,时间复杂度为O(1)。

最大堆的特性如下:

  1. 父结点的键值总是大于或者等于任何一个子节点的键值
  2. 每个结点的左子树和右子树都是一个最大堆

最小堆的特性如下:

  1. 父结点的键值总是小于或者等于任何一个子节点的键值
  2. 每个结点的左子树和右子树都是一个最小堆

算法思想:

     将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。

  1. 构建初始堆。一般升序采用大顶堆,降序采用小顶堆。从第一个非叶子结点从下至上,从右至左调整结构; 
  2. 交换堆顶元素和末尾元素,使最大值沉到数组末尾,重新调整堆结构,使其满足定义;
  3. 然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换,直到整个序列有序。

代码实现:

import java.util.Arrays;

public class 堆排序 {
	public static int[] heapSort(int[] arr){
		////调整堆要从最后一个非叶子节点开始
		for(int i=arr.length/2-1;i>=0;i--){
			adjustHeap(arr,i,arr.length);
		}
		//交换,再调整
		for(int j=arr.length-1;j>0;j--){
			swap(arr,0,j);
			adjustHeap(arr, 0, j);
		}
		return arr;
		
	}
	private static void swap(int[] arr, int i, int j) {
		int tmp=arr[i];
		arr[i]=arr[j];
		arr[j]=tmp;
		
	}
	public static void adjustHeap(int[] arr,int i,int length){
		int temp=arr[i];
		for(int k=i*2+1;k<length;k=k*2+1){
			if(k+1<length&&arr[k]<arr[k+1]){ //如果左子节点小于右子节点,k指向右子节点
				k++;
			}
			if(arr[k]>temp){
				arr[i]=arr[k];
				i=k;
			}else{
				break;
			}
		}
		arr[i]=temp; //把temp值放到最终的位置
	}
	
	public static void main(String[] args){
		int[] arr={9,8,7,6,5,4,3,2,1};
		heapSort(arr);
		System.out.println(Arrays.toString(arr));
	}
}

猜你喜欢

转载自blog.csdn.net/hellodake/article/details/82383907