堆排序

作者: 吕建雄 | 来源:发表于2020-01-17 11:56 被阅读0次

堆:是具有下列特性的完全二叉树;每个节点的值都大于或等于其左右孩子节点的值,称为大顶堆;或者每个节点的值都小于或等于其左右孩子节点的值,称为小顶堆

堆排序:(两个问题)

1、如何由一个无序序列构建成一个堆

2、如何在输出堆顶元素后,调整剩余元素成为一个新的堆

    将待排序的序列构建成一个大顶堆,其实就是从下往上、从右到左,将每个非终点节点当作根节点,将其和其子树调整成大顶堆

    将待排序的序列构造成一个大顶堆。此时整个序列的最大值就是堆顶的根节点。将它移走(其实就是将其与堆数组的末尾元素进行交换,此时末尾元素就是最大值),然后将剩余的n-1个序列重新构造成一个堆,这样就会得到n个元素中的次大值;如此反复,就能得到一个有序序列啦

class HeapSort {

    public static void main(String[] argv){

        int[] arr = {50,10,90,40,60,80,70,30,20};

        System.out.println("排序前...");

          for(int i=0;i<arr.length;i++){

            System.out.println(arr[i]);

        }

        System.out.println("排序后...");

        heapSort(arr);

        for(int i=0;i<arr.length;i++){

            System.out.println(arr[i]);

        }

    }

    //堆构造

    public static void heapBuilder(int[] arr, int s, int length){

        int k = s;

        int guard = arr[s];//哨兵对象

        //此处为什么index = 2*k+1完全二叉树的特性决定,第i个节点其左子节点为2i,右子节点为2i+1

        //而数组的索引从0开始,所以此处需要+1

        int index = 2*k +1;

        while(index<length){

            if(index+1 < length){

                if(arr[index]<arr[index+1]){

                    index++;

                }

            }

            if(arr[index] > guard){

                arr[k] = arr[index];

                k = index;

                index = 2*k +1;

            } else {

                break;

            }

        }

        arr[k] = guard;

    }

    public static void heapSort(int[] arr){

        //堆构造,从第一个非子叶节点开始(arr.length/2-1)

        for(int i=arr.length/2-1;i>=0;i--){

            heapBuilder(arr,i,arr.length);

        }

        for(int i = arr.length-1;i>0;i--){

            //通过交换,将最大值放入到堆的末尾

            int max = arr[0];

            arr[0] = arr[i];

            arr[i] = max;

            heapBuilder(arr,0,i);

        }

    }

}

代码实现

运行时间完全消耗在初始构建堆和重建堆时的反复筛选上

在构建堆的过程中,因为是完全二叉树从最下层最右边的非终点节点开始构建,将它与其孩子进行比较和有必要的交换,对于每个非终节点来说,最多两次比较和互换操作,因为整个构建堆的时间复杂度为O(n)

正式排序时,第i此取堆顶记录重建堆需要用O(logi)的时间(完全二叉树的每个节点到根节点的距离为log(2)i+1),并且需要取n-1次堆顶记录,因此重建堆的时间复杂度为O(nlogn)

总体来说,堆排序的时间复杂度为O(nlogn)

相关文章

  • 堆排序

    目录 1.堆排序介绍 2.堆排序图文说明 3.堆排序的时间复杂度和稳定性 4.堆排序实现 堆排序介绍 堆排序(He...

  • 堆排序---基础篇

    本文主要介绍堆排序的一些基本过程和分析。 大纲 堆排序简介 堆排序代码实现 1. 堆排序简介 1.1 堆排序的存储...

  • 堆和堆排序

    最小K个数 堆排序 堆排序

  • JS实现堆排序

    原理 堆排序原理 实现 说明 堆排序对大文件很有效 堆排序是不稳定排序

  • iOS算法总结-堆排序

    iOS算法总结-堆排序 iOS算法总结-堆排序

  • 堆排序

    转载:图解排序算法(三)之堆排序 预备知识 堆排序 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选...

  • 排序

    原创 堆排序: 使用visit数组从本质出发获取大顶堆排序。

  • 堆排序

    堆排序

  • C++基础入门之模板堆排序(上):模板上的list的创造与操作

    整段源码链接C++的模板元堆排序 要点 组建数据结构list 组建对list的各种基本操作 堆排序中组建堆排序个个...

  • 3.2-选择排序-堆排序

    参考链接 选择排序:堆排序(Heap Sort) 白话经典算法系列之七 堆与堆排序 堆排序与快速排序,归并排序一样...

网友评论

      本文标题:堆排序

      本文链接:https://www.haomeiwen.com/subject/fdeczctx.html