堆的应用(堆排序、TOP - K问题)

简介: 堆的应用(堆排序、TOP - K问题)

前言


🍎 时间复杂度:


🥝 堆排序的最坏时间复杂度为 :O(n*lg(n))


🥝 TOP - K问题的最坏时间复杂度为:O(n*lg(k))


   🍁前面我们学习了二叉树、以及堆的结构,也用顺序表的结构成功的把堆的结构一步一步的敲出来了。IT公司的吉祥“树” 二叉树-(堆)C语言创建_硕硕C语言的博客-CSDN博客(里面有一些树的基础知识,没有了解过的可以看一看,顺便来个三连应该不过分吧🥰)

,下面我将带领着大家来了解一下堆有什么应用、怎么用、用这个有什么好处。


aa576ded248ff784799a91cebedcaa1e_088af12c86fb73c397cc7dc17fbef027.jpeg


堆排序


       🚩堆排序即利用堆的思想来进行排序,总共分为两个步骤:


1. 建堆


🔴升序:建大堆

🔴降序:建小堆


2. 利用堆删除思想来进行排序


💧 建堆和堆删除中都用到了向下调整,因此掌握了向下调整,就可以完成堆排序。


思路:


⭕1.首先将待排序的数组构造成一个大根堆,此时,整个数组的最大值就是堆结构的顶端


⭕2.将顶端的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数组个数为n-1


⭕3.将剩余的n-1个数再构造成大根堆,再将顶端数与n-1位置的数交换,如此反复执行,便能得到有序数组

acff956cb8baaa53537d78ddc2487bf8_542ddac405076b05c61c7fccf606d4dd.gif

0334dbe189e09f4e0b459888af4fcb2a_41b3b816f5f110d88a98a378f6357cba.gif


3. 代码:

//堆排序
    public static void heapSort(int[] arr) {
        //构造大根堆
        heapInsert(arr);
        int size = arr.length;
        while (size > 1) {
            //固定最大值
            swap(arr, 0, size - 1);
            size--;
            //构造大根堆
            heapify(arr, 0, size);
        }
    }
    //构造大根堆(通过新插入的数上升)
    public static void heapInsert(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            //当前插入的索引
            int currentIndex = i;
            //父结点索引
            int fatherIndex = (currentIndex - 1) / 2;
            //如果当前插入的值大于其父结点的值,则交换值,并且将索引指向父结点
            //然后继续和上面的父结点值比较,直到不大于父结点,则退出循环
            while (arr[currentIndex] > arr[fatherIndex]) {
                //交换当前结点与父结点的值
                swap(arr, currentIndex, fatherIndex);
                //将当前索引指向父索引
                currentIndex = fatherIndex;
                //重新计算当前索引的父索引
                fatherIndex = (currentIndex - 1) / 2;
            }
        }
    }
    //将剩余的数构造成大根堆(通过顶端的数下降)
    public static void heapify(int[] arr, int index, int size) {
        int left = 2 * index + 1;
        int right = 2 * index + 2;
        while (left < size) {
            int largestIndex;
            //判断孩子中较大的值的索引(要确保右孩子在size范围之内)
            if (arr[left] < arr[right] && right < size) {
                largestIndex = right;
            } else {
                largestIndex = left;
            }
            //比较父结点的值与孩子中较大的值,并确定最大值的索引
            if (arr[index] > arr[largestIndex]) {
                largestIndex = index;
            }
            //如果父结点索引是最大值的索引,那已经是大根堆了,则退出循环
            if (index == largestIndex) {
                break;
            }
            //父结点不是最大值,与孩子中较大的值交换
            swap(arr, largestIndex, index);
            //将索引指向孩子中较大的值的索引
            index = largestIndex;
            //重新计算交换之后的孩子的索引
            left = 2 * index + 1;
            right = 2 * index + 2;
        }
    }
    //交换数组中两个元素的值
    public static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }


TOP - K问题


       🍪TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。对于Top-K问题,能想到的最简单直接的方式就是排序,但是:如果数据量非常大,排序就不太可取了(可能数据都不能一下子全部加载到内存中)。最佳的方式就是用堆来解决,基本思路如下:


1. 用数据集合中前K个元素来建堆


       ⭕前k个最大的元素,则建小堆

       ⭕前k个最小的元素,则建大堆


🚨🚨注意:只找到TopK,不排序TopK。


2. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素


🍁将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素。


图解:( 找前K大的数据 )😍


✅还是老套路上图解释(这里以找前K大的数据为例子)


       🍟1.  先用前k个元素生成一个小顶堆,这个小顶堆用于存储,当前最大的k个元素。


0d62136a3a4d25eaf02c7af09e270283_a53f4952b202413fbece46e04026bd9e.png


      🍟 2. 接着,从第k+1个元素开始扫描,和堆顶(堆中最小的元素)比较,如果被扫描的元素大于堆顶,则替换堆顶的元素,并调整堆,以保证堆内的k个元素,总是当前最大的k个元素。


700c57a5eff8dea9d54702cc5db691ab_7c2c5ea2c84249c09fd25d712f073b3d.png


       🍟3. 扫描完所有n-k个元素,最终堆中的k个元素,就是前K大的数据。


image.png


时间复杂度


🚩 TOP - K问题的时间复杂度为:O(n*lg(k))

🚩 堆排序的最坏时间复杂度为 :O(n*lg(n))


目录
相关文章
|
5月前
|
存储 算法
【数据结构】堆,堆的实现,堆排序,TOP-K问题
数据结构——堆,堆的实现,堆排序,TOP-K问题
49 1
【数据结构】堆,堆的实现,堆排序,TOP-K问题
|
7月前
【数据结构】二叉树-堆(top-k问题,堆排序,时间复杂度)
【数据结构】二叉树-堆(top-k问题,堆排序,时间复杂度)
53 4
|
7月前
堆的应用:堆排序和TOP-K问题
堆的应用:堆排序和TOP-K问题
48 0
|
7月前
|
算法 C语言
堆的应用:堆排序
堆的应用:堆排序
97 0
|
存储 C语言
堆与堆排序操作详解
堆与堆排序操作详解
|
算法 大数据 C语言
数据结构-堆的实现及应用(堆排序和TOP-K问题)(下)
数据结构-堆的实现及应用(堆排序和TOP-K问题)(下)
|
算法 C语言
数据结构-堆的实现及应用(堆排序和TOP-K问题)(上)
数据结构-堆的实现及应用(堆排序和TOP-K问题)(上)
堆(两种建堆方法)、堆排序和Top-K问题
堆(两种建堆方法)、堆排序和Top-K问题
|
存储
什么是堆,如何实现?(附堆排序,TOP-K问题)
什么是堆,如何实现?(附堆排序,TOP-K问题)
121 0
什么是堆,如何实现?(附堆排序,TOP-K问题)