经典的排序算法--堆排序
2017-03-25 10:05
190 查看
核心点:堆调整
如何形成最小堆/最大堆,那就先需要了解最小堆/最大堆的概念。
最大堆(大根堆)要求根节点的关键字既大于或等于左子树的关键字值,又大于或等于右子树的关键字值,且要求是完全二叉树。
调整过程:
保存当前节点值,当前节点为父节点;
通过父节点找到子节点;
如果子节点不存在,退出;否则,判断左右孩子中的大值节点,记录该节点;
如果父节点大于等于该大值节点,退出;否则,将大值节点与其父节点值交换,并将该子节点设为父节点,找到该节点的子节点;跳至3继续执行。
执行输出:
[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]
需要注意的是:最大堆每次将堆中最大值调整到数组尾部,所以得出的序列为升序序列。
如何形成最小堆/最大堆,那就先需要了解最小堆/最大堆的概念。
最大堆(大根堆)要求根节点的关键字既大于或等于左子树的关键字值,又大于或等于右子树的关键字值,且要求是完全二叉树。
调整过程:
保存当前节点值,当前节点为父节点;
通过父节点找到子节点;
如果子节点不存在,退出;否则,判断左右孩子中的大值节点,记录该节点;
如果父节点大于等于该大值节点,退出;否则,将大值节点与其父节点值交换,并将该子节点设为父节点,找到该节点的子节点;跳至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]
需要注意的是:最大堆每次将堆中最大值调整到数组尾部,所以得出的序列为升序序列。
相关文章推荐
- 经典排序算法学习笔记七——堆排序
- 漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析
- 经典排序算法 -----冒泡排序,插入排序,快速排序,归并排序,堆排序
- 漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析
- 经典排序算法2-堆排序及优先队列
- 五种经典排序算法的实现(冒泡、归并、快排、堆排序、希尔)
- 经典排序算法:堆排序(python)
- 五种经典排序算法的实现(冒泡、归并、快排、堆排序、希尔)
- 经典排序算法系列7----堆与堆排序
- 经典排序算法——堆排序(基本算法之一)
- 经典排序算法 - 堆排序Heap sort
- 漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析
- 漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析
- 漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析
- 七大基本排序算法之堆排序
- 图解排序算法(三)之堆排序
- Python练手之6种经典排序算法
- 排序算法五——堆排序
- 经典排序算法python回顾之一 交换排序
- 数据结构和算法分析之排序算法--选择排序(堆排序)