heapsort
堆排序
堆排序原理
利用最大堆顶部是最大值的特性,将最大堆顶部的值与最后一个元素交换,将最大值放在末位
假设数组[13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
代码如下
public static void main(String[] args) {
int[] sort = new int[]{13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
buildMaxHeapify(sort);
heapSort(sort);
System.out.println(Arrays.toString(sort));
}
初始化最大堆,堆的上一层数据是大于下一层的数据的
代码如下
static void buildMaxHeapify(int[] data) {
//没有子节点的才需要创建最大堆,从最后一个的父节点开始
int startIndex = getParentIndex(data.length - 1);
//从尾端开始创建最大堆,每次都是正确的堆
for (int i = startIndex; i >= 0; i--) {
maxHeapify(data, data.length, i);
}
}
static void maxHeapify(int[] data, int heapSize, int index) {
//当前点与左右子节点比较
int left = getChildLeftIndex(index);
int right = getChildRightIndex(index);
//记录最大节点位置
int largest = index;
//如果当前节点小于左节点,最大值则为左节点
if (left < heapSize && data[index] < data[left]) {
largest = left;
}
//如果当前节点小于右节点,最大值则为右节点
if (right < heapSize && data[largest] < data[right]) {
largest = right;
}
//得到最大值后可能需要交换,如果交换了,其子节点可能就不是最大堆了,需要重新调整
if (largest != index) {
int temp = data[index];
data[index] = data[largest];
data[largest] = temp;
maxHeapify(data, heapSize, largest);
}
}
如
13
12 11
10 9 8 7
6 5 4 3 2 1 0
第一层为13
第二层为12 11
第三层为10 9 8 7
第四层为6 5 4 3 2 1 0
上层数据必须大于下层数据
初始化最大堆之后,开始从数组的末位循环,每次将堆长度减1,
并将堆的最后一位和首位交换,交换完之后,再次生成最大堆,
此时堆顶又是最大值,再与之前交换值的位置的前一个位置值做交换。
代码如下
static void heapSort(int[] data) {
//末尾与头交换,交换后调整最大堆
for (int i = data.length - 1; i > 0; i--) {
int temp = data[0];
data[0] = data[i];
data[i] = temp;
maxHeapify(data, i, 0);
}
}
以下是堆得获取堆的左节点右节点以及父节点的代码
/**
* 父节点位置
*
* @param current 当前节点位置
* @return
*/
static int getParentIndex(int current) {
return (current - 1) >> 1;
}
/**
* 左子节点位置,注意括号,加法优先级更高
*
* @param current 当前节点位置
* @return
*/
static int getChildLeftIndex(int current) {
return (current << 1) + 1;
}
/**
* 右子节点位置
*
* @param current 当前节点位置
* @return
*/
static int getChildRightIndex(int current) {
return (current << 1) + 2;
}
注:后续会更新算法有关的代码
github地址为 https://github.com/liqingsanijn/algorithm