Algorithm-排序算法-堆排序

堆排序是选择类排序算法,核心思想依然是选择最大(小)的元素,与直接选择排序不同的是,堆排序借助了最大堆的特性,使得最大元素的查找更加的便利。

最大堆

最大堆是二叉堆的一个形式,最大堆要求根节点的关键字是所有节点关键字中的最大者,即要求最大堆根节点的关键字不小于其左叶子的关键字,也不能小于右叶子的关键字。这就要求最大堆:

  1. 最大堆的子树也是一个最大堆;
  2. 最大堆是完全二叉树,而且是根节点关键字大于等于左右叶子关键字的完全二叉树

既然最大堆是完全二叉树,则根节点与其叶子节点节点之间的存在以下关系:

  1. 子节点A[i]的父节点 A[Parent(i)]=A[(i-1)/2]
  2. 父节点i的左叶子节点 A[left(i)]=A[2*i+1]
  3. 父节点i的右叶子节点 A[left(i)]=A[2*i+2]

算法描述

  1. 通过待排序的无序队列自下而上构建最大堆;
  2. 交换最大堆首尾两个元素,则最大元素被交换到队尾,并移除已排序的最大元素
  3. 由于队列顶端新元素的加入破坏了原有的最大堆状态,重新调整为最大堆;
  4. 重复2)3)步骤,知道排序完成。

算法实现

1.调整当前堆为最大堆

/**
	 * 将堆调整当前的堆为最大堆
	 * 
	 */
	private static void ajustHeap(int[] arr, int parent, int heap_size) {
		// 比较左叶子和根节点
		int left = parent * 2 + 1;
		if (left >= heap_size)
			return;
		int max_index = parent;
		if (arr[left] > arr[parent]) {
			max_index = left;
		}
		int right = parent * 2 + 2;
		if (right < heap_size && arr[max_index] < arr[right]) {
			max_index = right;
		}
		// 保证当前节点为最大堆
		if (max_index != parent) {
			swap(arr, parent, max_index);
			// 新交换的元素所在的枝干要调整为最大堆
			ajustHeap(arr, max_index, heap_size);
		}

	}

2.构建最大堆

/**
	 * 构建最大堆
	 */
	private static void buildMaxHeap(int[] arr) {
		// 最后一个叶子节点的父节点
		int last_branch = (arr.length - 1) / 2;
		for (int i = last_branch; i >= 0; i--) {
			ajustHeap(arr, i, arr.length);
		}
	}

3.堆排序

public static void sort(int[] arr) {
		if (arr == null || arr.length < 2)
			return;
		// 构建最大堆
		buildMaxHeap(arr);
		int heap_size = arr.length;
		// 最大堆的顶元素为最大元素
		for (int i = arr.length - 1; i > 0; i--) {
			swap(arr, 0, i);
			ajustHeap(arr, 0, --heap_size);
		}
	}

 

你可能感兴趣的:(算法,算法研究)