堆排序

410 阅读2分钟

堆排序

前言

  • 完全二叉树定义: 除了最后一层之外每一层都被完全填充,并且所有节点都向左对齐
  • 堆排序: 大顶堆表示根节点的值都不小于其左右孩子 小顶堆表示根节点的值都不大于其左右孩子 可知大顶堆的根节点是整个数组中最大的。
  • 二叉树父子节点的关系 根节点A 左孩子节点就是2A+1 右孩子节点就是2A+2
  • 堆排序流程: 通过去构造大顶推每次构造之后最大元素在堆顶,然后把堆顶元素放在数组的末尾,不断的构造堆、交换、构造堆交换。完成数组的排序

排序流程

动图

代码

//建堆
    public static void buildHeap(int arr[],int curr,int size){
        if(curr<size){
			//左子树位置
            int left=2*curr+1;
			//右子树位置
            int right=2*curr+2;
            int max=curr;
            if(left<size){
			//左子树比当前节点大。记录位置
                if(arr[max]<arr[left]){
                    max=left;
                }
            }
			//右子树比当前节点大。记录位置
            if(right<size){
                if(arr[max]<arr[right]){
                    max=right;
                }
            }
            if(max!=curr){
			//如果最大的不是根元素位置,那么就交换
                int temp=arr[curr];
                arr[curr]=arr[max];
                arr[max]=temp;
			//以max节点为父节点继续建堆
                buildHeap(arr,max,size);
            }

        }
    }
  //从数组末尾开始去构建堆,实现整个数组符合一个大顶堆。 
   public static void maxHeap(int arr[],int size){
        for(int j=size-1;j>=0;j--){
            buildHeap(arr,j,size);
        }
    }
		
    public static void heapSort(int arr[]){
        for (int i = 0; i < arr.length; i++) {
            maxHeap(arr,arr.length-i);
			//将堆顶元素与数组最后位置交换。完成一次排序流程
            int temp=arr[0];
            arr[0]=arr[arr.length-1-i];
            arr[arr.length-1-i]=temp;
        }
    }

复杂度分析

堆排序是一种选择排序,整体主要由构建初始堆+交换堆顶元素和末尾元素并重建堆两部分组成。其中构建初始堆经推导复杂度为O(n),在交换并重建堆的过程中,需交换n-1次,而重建堆的过程中,根据完全二叉树的性质,[log2(n-1),log2(n-2)...1]逐步递减,近似为nlogn。所以堆排序时间复杂度最好和最坏情况下都是O(nlogn)级。

更多推荐

快速排序详解

冒泡排序详解

选择排序详解

插入排序详解

归并排序详解