您的位置:首页 > 其它

经典的排序算法--堆排序

2017-03-25 10:05 190 查看
核心点:堆调整

如何形成最小堆/最大堆,那就先需要了解最小堆/最大堆的概念。

最大堆(大根堆)要求根节点的关键字既大于或等于左子树的关键字值,又大于或等于右子树的关键字值,且要求是完全二叉树。

调整过程:

保存当前节点值,当前节点为父节点;

通过父节点找到子节点;

如果子节点不存在,退出;否则,判断左右孩子中的大值节点,记录该节点;

如果父节点大于等于该大值节点,退出;否则,将大值节点与其父节点值交换,并将该子节点设为父节点,找到该节点的子节点;跳至3继续执行。

import java.util.Arrays;

public class HeapSort {
public static void main(String[] args) {
int[] s = new int[] { 5, 1, 6, 7, 3, 2, 4, 9, 10, 8 };
HeapSort hs = new HeapSort();
hs.sort(s);
}

public void sort(int[] s) {
for (int i = s.length / 2 - 1; i >= 0; i--) {
adjustHeap(s, i, s.length);// 初始建立最大堆
}
System.out.println(Arrays.toString(s));
for (int i = s.length - 1; i > 0; i--) {
swap(s, 0, i);// 最大值调整到最后,其实得出的是升序
adjustHeap(s, 0, i);// 每次从根节点向下做出调整,由于每次都会得出一个有序数,所以i--
System.out.println(Arrays.toString(s));
}
}

public void adjustHeap(int[] s, int parent, int length) {
int tmp = s[parent];// 保存当前节点值
int child = 2 * parent + 1;// 左孩子
while (child < length) {
if (child + 1 < length && s[child] < s[child + 1]) {// 找左右孩子中的大值节点,如果是右孩子执行
child++;
}
if (s[parent] >= s[child]) {// 如果符合条件,退出调整
break;
} else {
s[parent] = s[child];
parent = child;
child = 2 * child + 1;// 继续探测孩子节点是否符合最大或者最小堆
}
s[parent] = tmp;// 如果发生调整则进行值交换,此时的parent值已经是其孩子节点
}
}

public void swap(int[] s, int a, int b) {
int tmp = s[a];
s[a] = s[b];
s[b] = tmp;
}
}


执行输出:

[10, 9, 6, 7, 8, 2, 4, 1, 5, 3]

[9, 8, 6, 7, 3, 2, 4, 1, 5, 10]

[8, 7, 6, 5, 3, 2, 4, 1, 9, 10]

[7, 5, 6, 1, 3, 2, 4, 8, 9, 10]

[6, 5, 4, 1, 3, 2, 7, 8, 9, 10]

[5, 3, 4, 1, 2, 6, 7, 8, 9, 10]

[4, 3, 2, 1, 5, 6, 7, 8, 9, 10]

[3, 1, 2, 4, 5, 6, 7, 8, 9, 10]

[2, 1, 3, 4, 5, 6, 7, 8, 9, 10]

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

需要注意的是:最大堆每次将堆中最大值调整到数组尾部,所以得出的序列为升序序列。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: