堆排序及java实现

Myth丶恋晨 2023-07-16 13:58 100阅读 0赞

堆排序是一种时间复杂度为O(nlgn)的一种排序算法,该排序算法用到的就是https://blog.csdn.net/john1337/article/details/104908523所说的大顶堆,大体思路就是将大顶堆的顶跟数组最后一个有效位置交换,然后对新构成的二叉堆进行大顶堆的重构,依次类推,最后数组就是一个从小往大递增的数组。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2pvaG4xMzM3_size_16_color_FFFFFF_t_70

  1. a

如上图所示的大顶堆,第一步就是把3与16交换位置,这样就会形成下面的数据
watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2pvaG4xMzM3_size_16_color_FFFFFF_t_70 1

  1. b

然后就会将16排除新的大顶堆的构造过程,新的大顶堆(不包括刚排除的16节点)如下图所示:

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2pvaG4xMzM3_size_16_color_FFFFFF_t_70 2

  1. c

好了,有了上面的基础,接下来看下用java来实现堆排序算法:

  1. /**
  2. * 堆排序
  3. * 有效数据从0开始,
  4. * 所以一个节点i,其对应二叉树左右子节点下标分别为2*i+1以及2*i+2
  5. */
  6. public class MaxHeapSort {
  7. @Test
  8. public void test(){
  9. int[] array= {2,8,14,4,16,7,1,10,9,3};
  10. heapSort(array);
  11. //输出堆排序结果
  12. for(int i:array){
  13. println(i);
  14. }
  15. }
  16. /**
  17. * 堆排序
  18. * @param array
  19. */
  20. public void heapSort(int[] array){
  21. //初始化大顶堆
  22. buildMaxHeap(array);
  23. //堆排序
  24. int heapSize = array.length;
  25. //最外层是循环次数,循环到最后大顶堆只有一个元素时停止,所以循环次数为array.length-1
  26. for(int i=0;i<array.length-1;i++){
  27. //交换a[0]与大顶堆最后一个元素(不包括已排好序的节点)
  28. swap(array,0,heapSize-1);
  29. //大顶堆数据减少一个
  30. heapSize--;
  31. //我这里array[0]也是有效数据,所以maxHeepify的第二个参数一致是0
  32. maxHeepify(array,0,heapSize);
  33. }
  34. }
  35. /**
  36. * 初始化大顶堆
  37. */
  38. private void buildMaxHeap(int[] array){
  39. int len = array.length;
  40. for(int i= (array.length-2)/2;i>=0;i--){
  41. maxHeepify(array,i,len);
  42. }
  43. }
  44. /**
  45. *
  46. * @param arr
  47. * @param i
  48. */
  49. private void maxHeepify(int[] arr,int i,int len){
  50. //println("i="+i);
  51. //有效数据下标从0开始
  52. //左子节点
  53. int left = 2*i+1;
  54. //右子节点
  55. int right = 2*i+2;
  56. //初始化最大值节点为当前节点
  57. int largest = i;
  58. //左节点不超出数组范围且比较大节点值大,则更新较大值下标
  59. if(left <len && arr[left] > arr[largest]){
  60. //左节点比该节点大
  61. largest = left;
  62. }
  63. //右节点不超出数组范围且比较大节点值大,则更新较大值下标
  64. if(right <len && arr[right] > arr[largest]){
  65. //左节点比该节点大
  66. largest = right;
  67. }
  68. //如果子节点有一个比当前节点大,则进行数据呼唤,同时向下递归
  69. if(largest != i){
  70. //交换节点i与较大子节点数据
  71. swap(arr,i,largest);
  72. //经过上面的调整后节点i与其两个子节点满足大顶堆条件
  73. //但是需要判断调整后的节点largest位置以及其子节点是否还满足大顶堆特性
  74. maxHeepify(arr,largest,len);
  75. }
  76. }
  77. private void swap(int[] arr,int i,int j){
  78. int tmp = arr[i];
  79. arr[i] = arr[j];
  80. arr[j] = tmp;
  81. }
  82. }

发表评论

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

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

相关阅读

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

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

    相关 排序-Java实现

    堆排序思想 对于给定的n个数据,初始时将n维数组看成一颗二叉树,若需要从小到大排序,将其调整为小顶堆(若从大到小排序,调整为大顶堆),输出堆顶元素,然后将堆的最后一个元素

    相关 排序 Java实现

    一、堆 在学习堆排序之前需要了解什么是堆? 堆是一颗完全二叉树,什么是完全二叉树? 若二叉树的深度为h,除了第h层外,其他各层的节点数都达到最大个数,第h层所有的