排序算法之堆排序及Java实现

傷城~ 2022-05-26 04:47 361阅读 0赞

一、排序算法的分类

  1. 选择排序(直接选择排序,堆排序)
  2. 交换排序(冒泡排序,快速排序)
  3. 插入排序(直接插入排序,希尔排序)
  4. 归并排序
  5. 桶式排序
  6. 基数排序

二、堆排序的原理

堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序。堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。
它的基本思想是将待排序的序列构造成一个大顶堆(或小顶堆)。此时,整个序列的最大值就是堆顶的根节点,将其与堆数组的末尾元素交换,此时末尾元素就是最大值,然后将剩余的 n-1 个序列重新构造成一个最大堆,再将新的最大堆的顶与末尾元素交换,如此反复执行,便能得到一个有序序列了。
这里写图片描述

三、堆排序的实现

堆排序中重要的一个部分是不断调整堆使其满足最大堆的性质,即父节点都比子节点的值大。调整最大堆的算法如下所示,输入为一个数组A和一个下标i,它用来维护以下标i为根结点的子树最大堆的性质,通过让A[i]的值在最大堆中“逐级下降”,从而使得以下标i为结点的子树重新遵循最大堆的性质。

这里写图片描述

之后用置底向上的方法利用MAX-HEAPIFY把一个大小为n=A.length的数组A[1~n]转化为最大堆。算法如下所示,原理很简单,就是从倒数第2层开始,调用MAX-HEAPFY方法,直至到根结点。
这里写图片描述

最后是取出最大值的算法,也就说将最大堆的顶值与最后一个节点值交换,这样最后一个节点就变成了最大值,再将前n-1个值重新进行最大堆排序。算法如下所示,首先将待排序的数组构建为最大堆数组,之后遍历整棵树,每次遍历“取出”根结点,再调用MAX-HEAPIFY维护子树的最大堆性质。这样就能保证遍历时每次“取出”的元素是当前剩余元素中最大的。

这里写图片描述

实现代码如下所示:

  1. public class HeapSort {
  2. public static void heapSort(int[] arr){
  3. buildMaxHeap(arr);
  4. int heapSize = arr.length;
  5. //最大值的节点与最后一个节点交换位置
  6. for (int i = arr.length - 1; i > 0; i--) {
  7. int temp = arr[i];
  8. arr[i] = arr[0];
  9. arr[0] = temp;
  10. //最后一个节点为最大值后,再对前边节点进行堆排序,每交换出一个最大值,最大堆的大小减1
  11. heapSize--;
  12. maxHeapify(arr, 0, heapSize);
  13. }
  14. }
  15. /**
  16. * 4 3 9 5 10 2 6
  17. * 0 1 2 3 4 5 6
  18. *
  19. * 4
  20. * 3 9
  21. * 5 10 2 6
  22. *
  23. * @param arr 待排序的数组
  24. * @param index 要进行调整的节点位置
  25. * @param heapSize 最大堆的大小
  26. */
  27. public static void maxHeapify(int[] arr, int index, int heapSize) {
  28. int leftIndex = 2 * index + 1;//左节点
  29. int rightIndex = 2 * index + 2;
  30. int largeIndex;//临时存储三个节点中最大的节点
  31. if (leftIndex < heapSize && arr[leftIndex] > arr[index]) {
  32. largeIndex = leftIndex;
  33. } else {
  34. largeIndex = index;
  35. }
  36. if (rightIndex < heapSize && arr[rightIndex] > arr[largeIndex]) {
  37. largeIndex = rightIndex;
  38. }
  39. if (largeIndex != index) {
  40. //与最大值的节点交换位置
  41. int temp = arr[largeIndex];
  42. arr[largeIndex] = arr[index];
  43. arr[index] = temp;
  44. //递归的方式对新的节点进行最大堆调整
  45. maxHeapify(arr, largeIndex, heapSize);
  46. }
  47. }
  48. //建立最大堆,遍历其中的非叶子节点,调整位置,达到最大堆的特点,即父节点的值大于子节点的值
  49. public static void buildMaxHeap(int[] arr) {
  50. int heapSize = arr.length;
  51. for (int i = (arr.length - 2) / 2; i > -1; i--) {
  52. maxHeapify(arr, i, heapSize);
  53. }
  54. }
  55. public static void main(String args[]){
  56. int[] test = {
  57. 4,3,9,5,10,2,6};
  58. heapSort(test);
  59. for(int i=0; i<test.length; i++){
  60. System.out.print(test[i] + " ");
  61. }
  62. }
  63. }

测试结果:

  1. 2 3 4 5 6 9 10

发表评论

表情:
评论列表 (有 0 条评论,361人围观)

还没有评论,来说两句吧...

相关阅读

    相关 排序算法排序

    排序算法-----堆排序 堆就是父节点值大于(大顶堆)子节点值或者父节点的值小于(小顶堆)子节点的值的完全二叉树,利用堆可以进行数组排序,如果要进行从小到大排序就

    相关 排序算法排序原理Java实现

    1、基本思想 堆是一种特殊的树形数据结构,其每个节点都有一个值,通常提到的堆都是指一颗完全二叉树,根结点的值小于(或大于)两个子节点的值,同时,根节点的两个子树也分别是一

    相关 Java排序算法排序

           “堆排序”是利用堆这种数据结构而设计的一种排序算法(注意这里和堆内存的区别,二者不同),它是一种选择排序,其平均时间复杂度是O(NlogN)。        这