数据结构与算法-堆排序

218 阅读1分钟

堆排序可以认为是对选择排序的优化,可以用二叉堆来实现,具体流程如下:

  1. 对序列原地建堆(heapify)
  2. 重复执行以下操作,指导堆元素的数量为1
  • 交换堆顶和堆尾元素
  • 堆的元素减1
  • 对堆顶元素进行一次下滤

堆排序过程

/**
 * 堆排序
 *
 * @author zhangj
 * @date 2020/9/23
 */
public class HeapSort {

	private int[] elements;

	private int size;

	/**
	 * 构造函数
	 *
	 * @param elements
	 */
	public HeapSort(int[] elements) {
		this.elements = elements;
	}

	/**
	 * 排序
	 */
	private void sort() {
		size = elements.length;
		//原地建堆
		for (int i = ((size >> 1) - 1); i >= 0; i--) {
			siftDown(i);
		}
		while (size > 1) {
			//交换堆头和堆尾元素
			int tmp = elements[0];
			elements[0] = elements[size - 1];
			elements[size - 1] = tmp;
			//数量减一
			size--;
			//堆头元素下滤
			siftDown(0);
		}
	}

	/**
	 * 下滤操作
	 *
	 * @param index
	 */
	private void siftDown(int index) {
		int value = elements[index];
		int half = size >> 1;
		while (index < half) {
			int leftIndex = (index << 1) + 1;
			int leftValue = elements[leftIndex];

			int rightIndex = leftIndex + 1;
			if (rightIndex < size) {
				int rightValue = elements[rightIndex];
				if (rightValue > leftValue) {
					leftIndex = rightIndex;
					leftValue = rightValue;
				}
			}

			if (value > leftValue) {
				break;
			}
			elements[index] = leftValue;
			index = leftIndex;
		}
		elements[index] = value;
	}
}

总结: 堆排序时间复杂度为O(nlogn),空间复杂度为O(1)