Java编程内功-数据结构与算法「堆排序」

开发 后端 算法
堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最好、最坏、平均时间复杂度均为O(nlogn),它是不稳定排序。

[[389058]]

 堆排序基本介绍

  1. 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最好、最坏、平均时间复杂度均为O(nlogn),它是不稳定排序。
  2. 堆是具有以下性质的完全二叉树:每个节点的值都大于等于其左右子节点的值,称为大顶堆,注意:没有要求最有子节点值得大小关系。
  3. 每个节点的值都小于等于左右子节点的值,称为小顶堆。
  4. 大顶堆的特点:arr[i ] >= arr[2i+1] && arr[i] >= arr[2i+2], i 对应第几个节点,i 从编号0开始。
  5. 小顶堆的特点: arr[i ] <= arr[2i+1] && arr[i] <= arr[2i+2], i 对应第几个节点,i 从编号0开始。
  6. 一般升序采用大顶堆,降序采用小顶堆。

堆排序基本思想

  1. 将待排序序列构造成一个大顶堆
  2. 此时,整个序列的最大值就是堆顶的根节点。
  3. 将其与数组末尾元素进行交换,此时末尾就为最大值。
  4. 然后将剩余 n-1 个元素重新构建成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列。

可以看到在构建大顶堆的过程中,元素的个数逐渐减少,最后得到一个有序序列了

一个数组中非叶子节点的个数 = arr.length / 2 - 1

代码案例

  1. package com.xie.tree; 
  2.  
  3. public class HeapSort { 
  4.     public static void main(String[] args) { 
  5.         int[] arr = new int[8000000]; 
  6.         for (int i = 0; i < 8000000; i++) { 
  7.             arr[i] = (int) (Math.random() * 800000000); 
  8.         } 
  9.         long start = System.currentTimeMillis(); 
  10.         heapSort(arr); 
  11.         long end = System.currentTimeMillis(); 
  12.         System.out.println("耗时:" + (end - start) + "ms"); 
  13.         /** 
  14.          * 800万数据 
  15.          * 堆排序!! 
  16.          * 耗时:2482ms 
  17.          */ 
  18.     } 
  19.  
  20.     public static void heapSort(int[] arr) { 
  21.         int temp = 0; 
  22.         System.out.println("堆排序!!"); 
  23.  
  24.         //1.将无序序列构成一个堆,根据升序降序需求选择大顶堆或小顶堆 
  25.         for (int i = arr.length / 2 - 1; i >= 0; i--) { 
  26.             adjustHeap(arr, i, arr.length); 
  27.         } 
  28.         //2.将堆顶元素与数组末尾元素交换,将最大元素"沉"到数组末端 
  29.         //3.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。 
  30.         for (int j = arr.length - 1; j > 0; j--) { 
  31.             //交换 
  32.             temp = arr[j]; 
  33.             arr[j] = arr[0]; 
  34.             arr[0] = temp
  35.             adjustHeap(arr, 0, j); 
  36.         } 
  37.     } 
  38.  
  39.     /** 
  40.      * 将一个数组(二叉树),调整成一个大顶堆 
  41.      * 功能:完成将以 i 对应的非叶子节点的树调整成大顶堆 
  42.      * 
  43.      * @param arr    待调整的数组 
  44.      * @param i      表示非叶子节点在数组的索引 
  45.      * @param length 表示对多少个元素进行调整,length在逐渐减少 
  46.      */ 
  47.     public static void adjustHeap(int[] arr, int i, int length) { 
  48.         //先取出当前元素的值,保存在临时变量 
  49.         int temp = arr[i]; 
  50.         //k = 2 * i + 1  是i节点的左子节点 
  51.         for (int k = 2 * i + 1; k < length; k = k * 2 + 1) { 
  52.             //当左子节点值小于右子节点值 
  53.             if (k + 1 < length && arr[k] < arr[k + 1]) { 
  54.                 k++;//k指向右子节点 
  55.             } 
  56.  
  57.             //如果子节点值大于父节点值 
  58.             if (arr[k] > temp) { 
  59.                 //把较大的值赋给当前节点 
  60.                 arr[i] = arr[k]; 
  61.                 //!!! i指向k 继续循环比较 
  62.                 i = k; 
  63.             } else { 
  64.                 break; 
  65.             } 
  66.         } 
  67.  
  68.         //当for循环结束后,我们已经将以 i 为父节点的树的最大值,放在了最顶。 
  69.  
  70.         //将temp值放到调整后的位置 
  71.         arr[i] = temp
  72.     } 

 【编辑推荐】

 

责任编辑:姜华 来源: 今日头条
相关推荐

2021-04-16 09:40:52

Java数据结构算法

2021-04-22 10:07:45

Java数据结构算法

2021-04-15 09:36:44

Java数据结构算法

2021-05-12 09:07:09

Java数据结构算法

2021-03-09 06:30:32

JAVA数据结构算法

2021-03-18 08:44:20

Java数据结构算法

2021-04-13 09:37:41

Java数据结构算法

2021-03-26 08:40:28

Java数据结构算法

2021-03-12 09:13:47

Java数据结构算法

2021-03-10 08:42:19

Java数据结构算法

2021-03-17 09:27:36

Java数据结构算法

2021-03-08 06:28:57

JAVA数据结构与算法稀疏数组

2021-03-29 10:13:47

Java编程数据结构算法

2021-04-07 09:26:37

Java数据结构算法

2021-03-14 08:27:40

Java数据结构算法

2021-05-13 07:34:56

Java数据结构算法

2021-04-23 09:12:09

Java数据结构算法

2021-03-11 08:53:20

Java数据结构算法

2021-03-24 10:41:04

Java数据结构算法

2021-05-08 08:28:38

Java数据结构算法
点赞
收藏

51CTO技术栈公众号