排序算法——堆排序

柔光的暖阳◎ 2022-12-22 08:41 324阅读 0赞

排序算法——堆排序

堆排序是利用堆这种数据结构所设计的一种排序算法。堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。升序采用大顶堆,降序采用小顶堆。大顶堆:arr[i] > >= arr[2i+1] && arr[i] >= arr[2i+2];小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]。

例如一组数组{9,8,7,6,5,4,3,2,1},先从最后一个非叶子节点(有子结点的结点)开始。也就是6(第一个非叶子节点:arr.length/2-1=9/2-1=3),再从左至右,从下至上进行调整。

第一个非叶子节点也就是6第一趟以6对子节点和父节点比较:子节点2和1都比6小,父节点8比6大,所以位置不发生改变。

第二个非叶子节点也就是7,第二趟以7对子节点和父节点比较:子节点4和3都比7小,父节点9比7大,所以位置不发生改变。

第三个非叶子节点也就是8,第三趟以8对子节点和父节点比较:子节点6和5都比8小,父节点9比8大,所以位置不发生改变。

第四个非叶子节点也就是9,第四趟以9对子节点和父节点比较:子节点8和7都比9小,没有父节点,所以位置不发生改变。

经过四趟后得到大顶堆{9,8,7,6,5,4,3,2,1}。如下图:
在这里插入图片描述
得到大顶堆后,将堆顶元素与末尾元素进行交换,使末尾元素最大。然后继续调整堆,再将堆顶元素与末尾元素交换,得到第二大元素。如此反复进行交换、重建、交换……

堆顶元素9与末尾元素1进行交换得到{1,8,7,6,5,4,3,2,9},继续调整堆得到{8,6,7,2,5,4,3,1,9},如下图:
在这里插入图片描述
堆顶元素8与末尾元素1进行交换得到{1,6,7,2,5,4,3,8,9},继续调整堆得到{7,6,4,2,5,1,3,8,9},如下图:
在这里插入图片描述
堆顶元素7与末尾元素3进行交换得到{3,6,4,2,5,1,7,8,9},继续调整堆得到{6,5,4,2,3,1,7,8,9},如下图:
在这里插入图片描述
堆顶元素6与末尾元素1进行交换得到{1,5,4,2,3,6,7,8,9},继续调整堆得到{5,3,4,2,1,6,7,8,9},如下图:
在这里插入图片描述
堆顶元素5与末尾元素1进行交换得到{1,3,4,2,5,6,7,8,9},继续调整堆得到{4,3,1,2,5,6,7,8,9},如下图:
在这里插入图片描述
堆顶元素4与末尾元素2进行交换得到{2,3,1,4,5,6,7,8,9},继续调整堆得到{3,2,1,4,5,6,7,8,9},如下图:
在这里插入图片描述
堆顶元素3与末尾元素1进行交换得到{1,2,3,4,5,6,7,8,9},继续调整堆得到{2,1,3,4,5,6,7,8,9},如下图:
在这里插入图片描述
堆顶元素2与末尾元素1进行交换得到{1,2,3,4,5,6,7,8,9},完成升序排序。

Java代码实现:
  1. public static void main(String[] args) {
  2. int[] arr = { 9,8,7,6,5,4,3,2,1};
  3. sort(arr);
  4. }
  5. public static void sort(int []arr)//堆排序
  6. {
  7. //构建大顶堆
  8. System.out.println("构建大顶堆——开始");
  9. for(int i=arr.length/2-1;i>=0;i--){
  10. //从第一个非叶子结点从下至上,从右至左调整结构
  11. adjustHeap(arr,i,arr.length);
  12. for (int l : arr) {
  13. System.out.print(l+",");
  14. }
  15. System.out.println();
  16. }
  17. System.out.println("构建大顶堆——结束");
  18. //调整堆结构+交换堆顶元素与末尾元素
  19. int z=0;
  20. for(int j=arr.length-1;j>0;j--){
  21. int temp=arr[0];
  22. arr[0] = arr[j];
  23. arr[j] = temp;//将堆顶元素与末尾元素进行交换
  24. adjustHeap(arr,0,j);//重新对堆进行调整
  25. z++;
  26. System.err.println("第"+z+"趟:");
  27. for (int l : arr) {
  28. System.out.print(l+",");
  29. }
  30. System.out.println();
  31. }
  32. }
  33. /** * 调整大顶堆 * @param arr * @param i * @param length */
  34. public static void adjustHeap(int []arr,int i,int length){
  35. int temp = arr[i];//先取出当前元素i
  36. for(int k=i*2+1;k<length;k=k*2+1){ //从i结点的左子结点开始,也就是2i+1处开始
  37. if(k+1<length && arr[k]<arr[k+1]){ //如果左子结点小于右子结点,k指向右子结点
  38. k++;
  39. }
  40. if(arr[k] >temp){ //如果子节点大于父节点,将子节点值赋给父节点(不用进行交换)
  41. arr[i] = arr[k];
  42. i = k;
  43. }else{
  44. break;
  45. }
  46. }
  47. arr[i] = temp;//将temp值放到最终的位置
  48. }
执行结果:

在这里插入图片描述

发表评论

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

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

相关阅读

    相关 排序算法——排序

    排序算法——堆排序 > 堆排序是利用堆这种数据结构所设计的一种排序算法。堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点

    相关 排序算法-排序

    堆是一个完全二叉树 堆排序是指利用堆这种数据结构所设计的一种排序算法 大顶堆:每个结点的值都大于或等于其左右孩子结点的值 arr\[i\] >= arr\[2i+1

    相关 排序算法-排序

    堆排序算法是建立在堆这种数据结构的基础上,其实堆听着很高端,其实很简单,就是一个二叉树,但是又特殊条件,就是其父节点比孩子节点都大(或都小)的堆称为最大堆(最小堆),瞬间感觉很

    相关 排序算法——排序

    前言 对于推排序它像合并排序而不像插入排序,堆排序的运行时间为O(nlogn)。像插入排序而不像合并排序,它是一种原地排序算法:在任何时候,数组中只有常数和元素存储在输入

    相关 排序算法排序

    一、前言     堆排序是一种选择排序。     选择排序:每趟从待排序的记录中选出关键字最小的记录,顺序放在已排序的记录序列末尾,直到全部排序结束为止。 ----

    相关 排序算法排序

      相关博客: [排序算法:冒泡排序、插入排序、选择排序、希尔排序][Link 1] [排序算法:归并排序、快速排序][Link 2] [排序算法:桶排序、计数排序、基

    相关 排序算法---排序

    二叉堆是完全二叉树或者是近似完全二叉树。 二叉堆满足二个特性: 1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。 2.每个结点的左子树和右子树都是一个二