堆排序的细节和复杂度分析------排序5

时间复杂度O(N*logN),额外空间复杂度O(1)

堆结构非常重要

1,堆结构的heapInsert与heapify

2,堆结构的增大和减少

3,如果只是建立堆的过程,时间复杂度为O(N)

4,优先级队列结构,就是堆结构

完全二叉树:叶子节点从左往右依次补齐

左节点:2*i +1

右节点:2*i+2

父节点:(i-1)/2

一个数组可以对应一个完全二叉树:

大根堆:这里的堆指的是完全二叉树,任何一个子树的最大值都是头部 比如下图:

heapInsert

一个数组可以对应一个完全二叉树,但是如何将一个数组变成大根堆

具体代码如下:

public static void heapSort(int[] arr) {
   if (arr == null || arr.length < 2) {
      return;
   }
   for (int i = 0; i < arr.length; i++) {
      //依次将添加i位置,形成大根堆
      heapInsert(arr, i);
   }

。。。。。

public static void heapInsert(int[] arr, int index) {
   while (arr[index] > arr[(index - 1) / 2]) {
      swap(arr, index, (index - 1) / 2);
      index = (index - 1) / 2;
   }
}

建立大根堆的时间复杂度:

log1+log2+log3......log(n-1)=O(n)

heapify

如果大根堆中形成的二叉树中某个值改变了,叫做heapify

如图:

假如6变成1

1)找到原始值6的左右孩子(根据公式),将左右俩个孩子进行比较,找到最大的那个

2)比较最大孩子是不是比1大,1和5交换,如下图:

3)1的左右孩子找到最大值5,最后交换结果:

具体代码如下:

public static void heapify(int[] arr, int index, int size) {
   int left = index * 2 + 1;
   while (left < size) {
      //left+1表示右孩子,left + 1 < size 判断右孩子是否越界
      //arr[left + 1] > arr[left]判断右孩子是否比左孩子大
      //int largest = left + 1 < size && arr[left + 1] > arr[left] ? left + 1 : left这句代码意思是找到左右孩子最大的那个
      int largest = left + 1 < size && arr[left + 1] > arr[left] ? left + 1 : left;
      //左右俩个孩子和当前的数值哪个大 的角标
      largest = arr[largest] > arr[index] ? largest : index;
      if (largest == index) {
         break;
      }
      //largest!=index,largest和index交换
      swap(arr, largest, index);
      index = largest;
      left = index * 2 + 1;
   }
}

heapsize解释:

如何将堆顶弹出:(减堆操作)

1)先让最后一个数和堆顶交换

2)将堆的大小减去1,原先是6,5,43,1对应角标0,1,2,3,4,现在是0,1,2,3,结构如下:

应用利用大根堆和小根堆求中位数:

大根堆每次弹出的值都是大根堆最大值,小根堆每次弹出都是最小值

堆排序就是利用堆结构完成的一个排序:

1)将数组变成大根堆

2)将最后一个位置和堆顶作交换,换完之后,最大值来到数组最后的位置,将堆的大小减去1,将剩下的数做heapify调整;

3)heapify后重新形成大根堆。。。循环

public static void heapSort(int[] arr) {
   if (arr == null || arr.length < 2) {
      return;
   }
   for (int i = 0; i < arr.length; i++) {
      //依次将添加i位置,形成大根堆
      heapInsert(arr, i);
   }
   int size = arr.length;
   swap(arr, 0, --size);
   while (size > 0) {
      heapify(arr, 0, size);
      swap(arr, 0, --size);
   }
}

猜你喜欢

转载自blog.csdn.net/qq_43193797/article/details/86739770