【算法&数据结构体系篇class06】:堆、大根堆、小根堆、优先队列

【数据结构】大根堆和小根堆 本篇文章详细介绍了大根堆和小根堆的实现逻辑和具体步骤,使用Java语言实现 阅读详情

一、堆结构

1)堆结构就是用数组实现的完全二叉树结构
2)完全二叉树中如果每棵子树的最大值都在顶部就是大根堆
3)完全二叉树中如果每棵子树的最小值都在顶部就是小根堆
4)堆结构的heapInsert与heapify操作
5)堆结构的增大add和减少poll
6)优先级队列结构,就是堆结构
  • heapInsert:

 入堆排序操作,从数组最后一个位置插入,然后再与其父节点(i-1)/2比较大小,大则交换上去,接着往其爷节点持续走..直到顶,或小于当前节点的父节点则停止,完成排序

  • heapify:

堆下沉排序操作 剔除元素后,需要将交换到根部的元素往下沉判断排序,如果大于左右节点就不用动,小于则与左右较大节点交换,并下沉继续判断,直到底部或者大于左右子节点

代码演示:

package class06;

import java.util.Comparator;
import java.util.PriorityQueue;

public class Heap {
    //大根堆 每个子树根节点比左右节点大
    public static class MyMaxHeap {
        private int[] heap;
        private int heapSize;
        private final int limit;

        public MyMaxHeap(int limit) {
            heap = new int[limit];
            heapSize = 0;
            this.limit = limit;
        }

        public boolean isEmpty() {
            return heapSize == 0;
        }

        public boolean isFull() {
            return limit == heapSize;
        }

        //入堆,同时保持堆的大根堆 有序
        public void push(int value) {
            if (isFull()) {
                throw new RuntimeException("堆已满,无法添加元素!");
            }
            //没满就赋值追加到数组后
            heap[heapSize] = value;
            //依次与该元素的父节点比较大小,大则交换两元素,然后接着往上走,直到顶或者不大于父节点,同时最后要把size+1
            heapInsert(heap, heapSize++);
        }

        //入堆操作,从数组最后一个位置插入,然后再与其父节点(i-1)/2比较大小,大则交换上去,接着往其爷节点持续走..直到顶,或小于当前节点的父节点则停止,完成排序
        private void heapInsert(int[] heap, int i) {
            //这个条件判断了两种情况,一个是大于父节点,一个是还没到顶节点(假如i来到顶部0 那么(i-1)/2也等0 为自己,是等于) 则继续循环。
            while (heap[i] > heap[(i - 1) / 2]) {
                swap(heap, i, (i - 1) / 2);
                i = (i - 1) / 2;
            }
        }

        //出堆,弹出最大值,顶部,然后保证当前堆仍有序 是大根堆
        public int pop() {
            if (isEmpty()) {
                throw new RuntimeException("堆已空,无法弹出元素!");
            }
            //弹出首元素,最大值
            int ans = heap[0];
            //然后把元素剔除两步  1.将首元素,与尾元素(heapSize是长度,尾元素是heapSize-1)交换,因为弹出操作,需要将heapSize 元素个数-1,两个操作只需要用--heapSize就能符合
            swap(heap, 0, --heapSize);
            //2.交换后表示将根节点元素剔除,然后需要确保现有堆的顺序
            heapify(heap, 0, heapSize);
            return ans;
        }

        //堆下沉排序操作 剔除元素后,需要将交换到根部的元素往下沉判断排序,如果大于左右节点就不用动,小于则与左右较大节点交换,并下沉继续判断,直到底部或者大于左右子节点
        private void heapify(int[] heap, int i, int heapSize) {
            //首先判断是否存在左子节点,左节点索引是i*2+1,不能超过heapSize-1尾索引,如果超过那肯定就到最后一个元素,右节点是比左节点大1 也更不会存在
            while (i * 2 + 1 < heapSize) {
                //此时确定有左节点,但需要判断是否有右节点i*2+2 如果有 并且大于左节点,那么左右节点较大值就是右节点,否则就是左节点
                int largest = i*2+2 < heapSize && heap[i*2+2]>heap[i*2+1]?i*2+2:i*2+1;
                //然后把较大的节点与父节点比较,谁大则重新赋值 largest最大值
                largest = heap[largest] > heap[i]?largest:i;
                if(largest == i) break; //如果判断后这个最大值位置就是父节点位置,相当于父节点都大于子节点,那么就不用交换,再下沉,此时已经完成排序,大的仍旧在前面,小的在下面,直接退出循环
                //子节点大于当前节点,那么与其较大的节点交换,交换完之后,当前节点i要来到较大节点largest位置 循环下沉
                swap(heap,i,largest);
                i = largest;
            }
        }
        private void swap(int[] heap, int i, int j) {
            int temp = heap[i];
            heap[i] = heap[j];
            heap[j] = temp;
        }
    }

    public static class RightMaxHeap {
        private int[] arr;
        private final int limit;
        private int size;

        public RightMaxHeap(int limit) {
            arr = new int[limit];
            this.limit = limit;
            size = 0;
        }

        public boolean isEmpty() {
            return size == 0;
        }

        public boolean isFull() {
            return size == limit;
        }

        public void push(int value) {
            if (size == limit) {
                throw new RuntimeException("heap is full");
            }
            arr[size++] = value;
        }

        public int pop() {
            int maxIndex = 0;
            for (int i = 1; i < size; i++) {
                if (arr[i] > arr[maxIndex]) {
                    maxIndex = i;
                }
            }
            int ans = arr[maxIndex];
            arr[maxIndex] = arr[--size];
            return ans;
        }

    }

    //比较器用于排序
    public static class MyComparator implements Comparator<Integer>{
        @Override
        public int compare(Integer o1, Integer o2) {
            return o2-o1; //降序
        }
    }

    public static void main(String[] args) {

        // 大根堆   优先队列默认是小根堆,通过比较器降序排序实现大根堆
        PriorityQueue<Integer> heap = new PriorityQueue<>(new MyComparator());
        heap.add(5);
        heap.add(5);
        heap.add(5);
        heap.add(3);
        // 5 , 3
        System.out.println(heap.peek());
        heap.add(7);
        heap.add(0);
        heap.add(7);
        heap.add(0);
        heap.add(7);
        heap.add(0);
        System.out.println(heap.peek());
        while (!heap.isEmpty()) {
            System.out.println(heap.poll());
        }

        int value = 1000;
        int limit = 100;
        int testTimes = 1000000;
        for (int i = 0; i < testTimes; i++) {
            int curLimit = (int) (Math.random() * limit) + 1;
            MyMaxHeap my = new MyMaxHeap(curLimit);
            RightMaxHeap test = new RightMaxHeap(curLimit);
            int curOpTimes = (int) (Math.random() * limit);
            for (int j = 0; j < curOpTimes; j++) {
                if (my.isEmpty() != test.isEmpty()) {
                    System.out.println("Oops!");
                }
                if (my.isFull() != test.isFull()) {
                    System.out.println("Oops!");
                }
                if (my.isEmpty()) {
                    int curValue = (int) (Math.random() * value);
                    my.push(curValue);
                    test.push(curValue);
                } else if (my.isFull()) {
                    if (my.pop() != test.pop()) {
                        System.out.println("Oops!");
                    }
                } else {
                    if (Math.random() < 0.5) {
                        int curValue = (int) (Math.random() * value);
                        my.push(curValue);
                        test.push(curValue);
                    } else {
                        if (my.pop() != test.pop()) {
                            System.out.println("Oops!");
                        }
                    }
                }
            }
        }
        System.out.println("finish!");

    }
}

二、堆排序,默认都是升序排序

1,先让整个数组都变成大根堆结构,建立堆的过程:
1)从上到下的方法,时间复杂度为O(N*logN)
2)从下到上的方法,时间复杂度为O(N)
2,把堆的最大值和堆末尾的值交换,然后减少堆的大小之后,再去调整堆,一直周而复始,时间复杂度为O(N*logN)
3,堆的大小减小成0之后,排序完成
  • 手写堆结构来进行排序操作

代码演示:

package class06;

import java.util.Arrays;
import java.util.PriorityQueue;

public class HeapSort {
    /**
     * 堆排序 利用堆的heapInsert heapify操作实现
     * @param arr
     */
    public static void heapSort(int[] arr){
        if(arr == null || arr.length < 2) return;
        //1.先使数组转换成一个大根堆,heapInsert heapify都可以 后者的时间复杂度更低,从下往上 时间复杂度O(N)
       int heapSize = arr.length;
        for(int i = arr.length-1;i>=0;i--){
            heapify(arr,i,heapSize);
        }
        //O(N*logN)
//        for(int i = 0;i<arr.length;i++){
//            heapInsert(arr,i);
//        }
        //2、首位交换,把最大值放到尾部,因为排序我们按降序,最大值就是放到尾部
        swap(arr,0,--heapSize);
        //3.依次开始进行堆下沉操作 直到排完序
        // O(N*logN)
        while(heapSize > 0){ //O(N)
            heapify(arr,0,heapSize); //O(logN)
            swap(arr,0,--heapSize); //O(1)
        }
    }
    public static void heapInsert(int[] arr, int i){
        while ( arr[i] > arr[(i-1)/2]){
            swap(arr,i,(i-1)/2);
            i = (i-1)/2;
        }
    }
    public static void heapify(int[] arr, int i, int heapSize){
        int left = i*2+1;
        while(left < heapSize){
            int largest = left + 1 < heapSize && arr[left + 1] >arr[left]?left+1:left;
            largest = arr[largest] > arr[i] ? largest : i;
            if(largest == i) break;
            swap(arr,i,largest);
            i = largest;
            left = i*2+1;
        }
    }

    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    // for test
    public static void comparator(int[] arr) {
        Arrays.sort(arr);
    }

    // for test
    public static int[] generateRandomArray(int maxSize, int maxValue) {
        int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
        }
        return arr;
    }

    // for test
    public static int[] copyArray(int[] arr) {
        if (arr == null) {
            return null;
        }
        int[] res = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            res[i] = arr[i];
        }
        return res;
    }

    // for test
    public static boolean isEqual(int[] arr1, int[] arr2) {
        if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
            return false;
        }
        if (arr1 == null && arr2 == null) {
            return true;
        }
        if (arr1.length != arr2.length) {
            return false;
        }
        for (int i = 0; i < arr1.length; i++) {
            if (arr1[i] != arr2[i]) {
                return false;
            }
        }
        return true;
    }

    // for test
    public static void printArray(int[] arr) {
        if (arr == null) {
            return;
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    // for test
    public static void main(String[] args) {

        // 默认小根堆
        PriorityQueue<Integer> heap = new PriorityQueue<>();
        heap.add(6);
        heap.add(8);
        heap.add(0);
        heap.add(2);
        heap.add(9);
        heap.add(1);

        while (!heap.isEmpty()) {
            System.out.println(heap.poll());
        }

        int testTime = 500000;
        int maxSize = 100;
        int maxValue = 100;
        boolean succeed = true;
        for (int i = 0; i < testTime; i++) {
            int[] arr1 = generateRandomArray(maxSize, maxValue);
            int[] arr2 = copyArray(arr1);
            heapSort(arr1);
            comparator(arr2);
            if (!isEqual(arr1, arr2)) {
                succeed = false;
                break;
            }
        }
        System.out.println(succeed ? "Nice!" : "Fucking fucked!");

        int[] arr = generateRandomArray(maxSize, maxValue);
        printArray(arr);
        heapSort(arr);
        printArray(arr);
    }
}

三、限定条件下堆排序:假设每个元素移动的距离一定不超过k,并且k相对于数组长度来说是比较小的

题意:
已知一个几乎有序的数组。几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离一定不超过k,并且k相对于数组长度来说是比较小的。 请选择一个合适的排序策略,对这个数组进行排序。

思路:
小根堆排序、优先队列:题目中提到了一个,每个元素移动的距离一定不超过k,那么就说明,从第一个数开始,前k+1个数里面,存在一个数,是一定要排在0位置的,这样才能使得移动不超过k个, 比如一个数组最小是1,长度为8,k=5,最小1是需要排在索引0位置的,为了满足移动不超过5个位置,那么在arr[0-k]区间内必然有1,最远只能在rr[k],那么也是移动k为来到0 k-k=0 ,利用这个特性,用小根堆,先把前k个数[0,k-1]入堆,然后第二次开始,从[k,arr.length-1]入堆,入一次 就依次从头赋值给原数组,然后再出堆;比如前面例子,第一次肯定是把1赋值给arr[0],出堆,往后入堆,赋值arr[1],出堆..直到最后一个元素,最后可能堆还有元素,就依次赋值给后面的数组位置,依次出堆,完成堆排序

代码演示:(这里不手写堆结构,一般都是直接用PriorityQueue优先队列,默认小根堆排序,说是优先队列,其实也是堆结构实现的)

 package class06;

import java.util.Arrays;
import java.util.PriorityQueue;

/**题意:
 * 已知一个几乎有序的数组。几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离一定不超过k,并且k相对于数组长度来说是比较小的。
 * 请选择一个合适的排序策略,对这个数组进行排序。
 *
 * 思路:小根堆排序、优先队列:题目中提到了一个,每个元素移动的距离一定不超过k,那么就说明,从第一个数开始,前k+1个数里面,存在一个数,是一定要排在0位置的
 * 这样才能使得移动不超过k个, 比如一个数组最小是1,长度为8,k=5,最小1是需要排在索引0位置的,为了满足移动不超过5个位置,那么在arr[0-k]
 * 区间内必然有1,最远只能在rr[k],那么也是移动k为来到0 k-k=0 ,利用这个特性,用小根堆,先把前k个数[0,k-1]入堆,然后第二次开始,从[k,arr.length-1]
 * 入堆,入一次 就依次从头赋值给原数组,然后再出堆;比如前面例子,第一次肯定是把1赋值给arr[0],出堆,往后入堆,赋值arr[1],出堆..直到最后一个元素,
 * 最后可能堆还有元素,就依次赋值给后面的数组位置,依次出堆,完成堆排序
 */
public class SortArrayDistanceLessK {
    public static void sortArrayDistanceLessK(int[] arr, int k){
        if(arr == null || arr.length <2) return;
        PriorityQueue<Integer> heap = new PriorityQueue<>();
        //技巧:把堆索引定义外面,定义for里面的话就没法给,后续的操作使用
        int index = 0;
        //1.首先我们把0,k-1的区间先入堆,下次开始入k时,就时要开始循环赋值、出堆,因为arr[k] 前面有k个数,
        //题目限定每个元素移动不超过k ,那么排在arr[0]的数,肯定就是再0,k区间内,所以再k入堆时,就可以出堆,其
        //最小值就是位于arr[0]
        //判断最小值是因为我们测试用例的k范围是随机的可能会大于数组长度
        for(;index < Math.min(arr.length-1,k);index++){
            heap.add(arr[index]);
        }
        //2.此时index = k ,开始往后遍历,index不超过数组长度 赋值,出堆
        //定义数组从0开始的下标 用于赋值
        int indexArr = 0;
        for(;index<arr.length;index++,indexArr++){
            heap.add(arr[index]);
            //出堆,赋值,出堆是因为该值已经赋值到数组了,就需要排除
            arr[indexArr] = heap.poll();
        }
        //3.此时遍历到最后,堆可能还有元素,需要依次再赋值到arr[indexArr]位置
        while(!heap.isEmpty()){
            arr[indexArr++] = heap.poll();
        }
    }

    // for test
    public static void comparator(int[] arr, int k) {
        Arrays.sort(arr);
    }

    // for test
    public static int[] randomArrayNoMoveMoreK(int maxSize, int maxValue, int K) {
        int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
        }
        // 先排个序
        Arrays.sort(arr);
        // 然后开始随意交换,但是保证每个数距离不超过K
        // swap[i] == true, 表示i位置已经参与过交换
        // swap[i] == false, 表示i位置没有参与过交换
        boolean[] isSwap = new boolean[arr.length];
        for (int i = 0; i < arr.length; i++) {
            int j = Math.min(i + (int) (Math.random() * (K + 1)), arr.length - 1);
            if (!isSwap[i] && !isSwap[j]) {
                isSwap[i] = true;
                isSwap[j] = true;
                int tmp = arr[i];
                arr[i] = arr[j];
                arr[j] = tmp;
            }
        }
        return arr;
    }

    // for test
    public static int[] copyArray(int[] arr) {
        if (arr == null) {
            return null;
        }
        int[] res = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            res[i] = arr[i];
        }
        return res;
    }

    // for test
    public static boolean isEqual(int[] arr1, int[] arr2) {
        if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
            return false;
        }
        if (arr1 == null && arr2 == null) {
            return true;
        }
        if (arr1.length != arr2.length) {
            return false;
        }
        for (int i = 0; i < arr1.length; i++) {
            if (arr1[i] != arr2[i]) {
                return false;
            }
        }
        return true;
    }

    // for test
    public static void printArray(int[] arr) {
        if (arr == null) {
            return;
        }
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    // for test
    public static void main(String[] args) {
        System.out.println("test begin");
        int testTime = 500000;
        int maxSize = 100;
        int maxValue = 100;
        boolean succeed = true;
        for (int i = 0; i < testTime; i++) {
            int k = (int) (Math.random() * maxSize) + 1;
            int[] arr = randomArrayNoMoveMoreK(maxSize, maxValue, k);
            int[] arr1 = copyArray(arr);
            int[] arr2 = copyArray(arr);
            sortArrayDistanceLessK(arr1, k);
            comparator(arr2, k);
            if (!isEqual(arr1, arr2)) {
                succeed = false;
                System.out.println("K : " + k);
                printArray(arr);
                printArray(arr1);
                printArray(arr2);
                break;
            }
        }
        System.out.println(succeed ? "Nice!" : "Fucking fucked!");
    }

}

四、最大线段重合问题(用堆的实现)

题意:
给定很多线段,每个线段都有两个数[start, end],
表示线段开始位置和结束位置,左右都是闭区间
规定:
1)线段的开始和结束位置一定都是整数值
2)线段重合区域的长度必须>=1
返回线段最多重合区域中,包含了几条线段

思路:
1.先将原二维数组,按arr[i][0] 起点位置进行升序排序
2.然后创建一个小根堆,遍历线段数组,如果堆内非空并且元素小于等于线段数组起点arr[i][0],就将元素出堆
3.最后将当前线段数组的终点arr[i][1]入堆,当前堆大小表示当前线段数组起点arr[i][0]有重叠的线段段数
4.依次比较每次的重叠线段数 刷新最大值,最后返回该最大值即为题目求的最大线段重合数
package class07;

import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;

/**题意:
 * 最大线段重合问题(用堆的实现)
 * 给定很多线段,每个线段都有两个数[start, end],
 * 表示线段开始位置和结束位置,左右都是闭区间
 * 规定:
 * 1)线段的开始和结束位置一定都是整数值
 * 2)线段重合区域的长度必须>=1
 * 返回线段最多重合区域中,包含了几条线段
 * 比如[1,3] [2,5],[2,8]这里三段都是重合,所以[2,5]重叠区间,结果为3  [1,3] [3,5] 这里没有重叠,只是边界重叠,重叠要保证是长度大于0的 结果为0
 *
 * 思路:
 * 1.先将原二维数组,按arr[i][0] 起点位置进行升序排序
 * 2.然后创建一个小根堆,遍历线段数组,如果堆内非空并且元素小于等于线段数组起点arr[i][0],就将元素出堆
 * 3.最后将当前线段数组的终点arr[i][1]入堆,当前堆大小表示当前线段数组起点arr[i][0]有重叠的线段段数
 * 4.依次比较每次的重叠线段数 刷新最大值,最后返回该最大值即为题目求的最大线段重合数
 */

public class CoverMax {
    //用于验证,不推荐该写法
    public static int maxCover1(int[][] lines) {
        int min = Integer.MAX_VALUE;
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < lines.length; i++) {
            //得到全部的线段包含在哪个边界上
            min = Math.min(min, lines[i][0]);
            max = Math.max(max, lines[i][1]);
        }
        int cover = 0;
        //为什么是加0.5 用小数来累加1是因为这里线段都是整数边界,需要判断是否有重叠,重叠区间某个数,无法确定整数,因为整数也可能是
        //边界重叠,但没有长度,而设一个小数,不管是零点几,都可以,只要重叠了,那么这区间肯定是有个小数的。所以就用每个小数累加1判断
        //从最小边界到最大边界, 看每个小数在整个区间的线段内有多少个重叠,标记保存到cover,循环下一个小数看看有多少个重叠,与cover保存
        //的值比较大小,更新重叠最大值
        for (double p = min + 0.5; p < max; p += 1) {
            int cur = 0;
            for (int i = 0; i < lines.length; i++) {
                if (lines[i][0] < p && lines[i][1] > p) {
                    cur++;
                }
            }
            cover = Math.max(cover, cur);
        }
        return cover;
    }

    //定义一个类结构保存每个线段的起点终点
    public static class Line{
        public int start;
        public int end;
        public Line(int s,int e){
            start = s;
            end = e;
        }}
    public static int maxCover2(int[][] arr){
        //创建保存线段起止点的类数组,长度自然就是二维数组的长度 有多少对
        Line[] lines = new Line[arr.length];
        for(int i = 0; i< arr.length;i++){
            lines[i] = new Line(arr[i][0],arr[i][1]);
        }
        //对该对象数组,按start起点升序排序,相当于固定起点顺序 从小开始,排序之后,
        //从起点小的开始才能确保每段是否存在重叠
        Arrays.sort(lines,(a,b)->(a.start-b.start));
        //定义一个结果值 ,保存最大重叠的段数 小根堆,保存的是每段的终点值,小的排顶部。堆的大小就是表示每次的线段起点重叠的线段数
        int ans = 0;
        PriorityQueue<Integer> heap = new PriorityQueue<>();
        //开始遍历排好序的线段组,
        for(int i = 0;i<lines.length;i++){
            //先要判断当前堆是否空,如果不为空,并且存在有比当前起点小于等于的元素,元素即保存的是
            //其前面起点比当前小或等于的线段的终点, 那么就要弹出,因为前面的线段终点小于等于当前线段
            //起点,说明没有重叠长度,即使相等,也不符合题意要求,需要长度大于0,相交则为0,大于起点值,
            //说明有几个元素,就是表示前面有几段线段与当前段重叠
            while(!heap.isEmpty() && heap.peek() <= lines[i].start){
                heap.poll();
            }
            //接着将当前段的终点入堆。
            heap.add(lines[i].end);
            //将定义的最大值变量,遍历与每次堆的长度比较大小,长度即表示当前段位起点有多少线段是重叠的。
            ans = Math.max(ans,heap.size());
        }
        return ans;
    }

    //不用类数组保存线段的写法,精简,推荐改写法
    public static int maxCover3(int[][] arr){
        //直接将当前二维数组进行排序,按元素的第一个索引元素排,也就是线段的起点升序
        Arrays.sort(arr,(a,b)->{
            return a[0]-b[0];
        });
        //定义小根堆,保存线段的终点值,堆内有多少个元素,就表示当前线段起点开始有多少个重合线段
        PriorityQueue<Integer> heap = new PriorityQueue<>();
        int ans = 0;
        //遍历排序好的线段
        for(int[] line:arr){
            //判断如果堆不为空,且堆有小于等于该线段起点的元素,就一直弹出,因为那些没有重叠
            while(!heap.isEmpty() && heap.peek() <= line[0]){
                heap.poll();
            }
            //终点入堆
            heap.add(line[1]);
            //更新重叠的最大线段数,堆大小就表示当前以该线段起点有多少个线段重叠
            ans = Math.max(ans,heap.size());
        }
        return ans;
    }

    // for test
    public static int[][] generateLines(int N, int L, int R) {
        int size = (int) (Math.random() * N) + 1;
        int[][] ans = new int[size][2];
        for (int i = 0; i < size; i++) {
            int a = L + (int) (Math.random() * (R - L + 1));
            int b = L + (int) (Math.random() * (R - L + 1));
            if (a == b) {
                b = a + 1;
            }
            ans[i][0] = Math.min(a, b);
            ans[i][1] = Math.max(a, b);
        }
        return ans;
    }

    public static class StartComparator implements Comparator<Line> {

        @Override
        public int compare(Line o1, Line o2) {
            return o1.start - o2.start;
        }

    }

    public static void main(String[] args) {

        Line l1 = new Line(4, 9);
        Line l2 = new Line(1, 4);
        Line l3 = new Line(7, 15);
        Line l4 = new Line(2, 4);
        Line l5 = new Line(4, 6);
        Line l6 = new Line(3, 7);

        // 底层堆结构,heap
        PriorityQueue<Line> heap = new PriorityQueue<>(new StartComparator());
        heap.add(l1);
        heap.add(l2);
        heap.add(l3);
        heap.add(l4);
        heap.add(l5);
        heap.add(l6);

        while (!heap.isEmpty()) {
            Line cur = heap.poll();
            System.out.println(cur.start + "," + cur.end);
        }

        System.out.println("test begin");
        int N = 100;
        int L = 0;
        int R = 200;
        int testTimes = 200000;
        for (int i = 0; i < testTimes; i++) {
            int[][] lines = generateLines(N, L, R);
            int ans1 = maxCover1(lines);
            int ans2 = maxCover2(lines);
            int ans3 = maxCover3(lines);
            if (ans1 != ans2 || ans1 != ans3) {
                System.out.println("Oops!");
            }
        }
        System.out.println("test end");
    }




}

如何构建一个大根堆 数组可以看成是一个完全二叉树,大根堆是一个完全二叉树 构造大根堆 例子1:[O(N)----&gt;从下到上] 因为堆是对父节点-左/右孩子节点之间的约束,所以从最后一个非叶子节点开始调整。 注意每次交换后,都要对下一层的子堆进行递归调整,因为交换后有可能破坏已调整子堆的结构。 堆排序 例子2:[O(N)----&gt;从下到上] 1、假设给定无序序列结构如下 2.此时我们从最后一个非叶子结点开始(叶结点自然不用调整,第一个非叶子结点 arr.length/2-1=5/2-1=1,也就是下面的6结点) 阅读详情

相关推荐

数据结构--堆的实现-大根堆/小根堆/堆排序/堆排序稳定性证明/TOP-K

逆水行舟,不进则退!!!

m0_63852716的博客 3213

堆(大根堆、小根堆)

本文介绍完全二叉堆,包括大根堆、小根堆。相关的算法堆(大根堆、小根堆)的插入、删除、批量建立。

pingdaozhang的博客 5万+

【数据结构】堆,大根堆,小根堆,优先队列 详解

堆 要了解堆之前,请先了解树,因为堆是一颗完全二叉树 如果不知道的话请点击下方链接了解 树,二叉树,完全二叉树详解 要注意的是 首先堆是一颗完全二叉树 其次堆中存储的值是偏序 Min-heap(小根堆): 父节点的值小于或等于子节点的值 Max-heap(大根堆): 父节点的值大于或等于子节点的值 好吧其实就是实现自动排序 O(logn)时间复杂度内实现插入,删除,O(1)查询 1....

繁凡さん的博客 1万+

大根堆、小根堆(数组模拟操作)

1.什么是大根堆、小根堆? 首先堆应该是一颗完全二叉树,大根堆就是二叉树的所有父节点的值都比左右孩子的值大,小根相反。下面是大根堆和小根堆的图: 如上,左图是一个大根堆,右图是一个小根堆。 2.树的数组存储 我们可以将树存储在一个数组中: 根结点存储在位置0,根的左孩子存储在位置1,右孩子存储在位置2。由此可以得出如下公式: 如果父节点的位置为i,那么他的左孩子和右孩子的位置分别为...

李志杰的博客 1万+

HTML5期末大作业:关于家乡介绍的HTML网页设计——郑州美景HTML+CSS(5页) 学生DW家乡介绍网页设计作业成品 web课程设计网页规划与设计

HTML5期末大作业:我的家乡——郑州美景HTML+CSS(5页) 学生DW网页设计作业成品 web课程设计网页规划与设计 计算机毕设网页设计源码 常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫、 明星、 服装、 体育、 化妆品、 物流、 环保、 书籍、 婚纱、 游戏、 节日、 戒烟、 电影、 摄影、 文化、 家乡、 鲜花、 礼品、 汽车、 其他 等网页设计题目, A+水平作业, 可满足大学生网页大作业网页设计需求, 喜

qq_365392777 1万+

Orange:一个基于 Python 的数据挖掘和机器学习平台

Orange是一个开源的数据挖掘和机器学习平台,采用可视化编程方式,用户可通过拖拽组件构建数据分析工作流。它支持交互式数据探索、多种机器学习算法,并允许Python脚本扩展。Orange特别适合教育和研究,提供直观的界面和丰富的可视化工具。最新版本为3.39.0,支持Windows、macOS和Linux系统。作为GPL许可的免费工具,它既能满足初学者需求,又能通过Python集成实现高级功能。

likuoelie的博客 1435

从 C 语言驱动你的数字人:Mesh Avatar Studio FFI 接口与嵌入实战

[Mesh Avatar Studio](https://link.gitcode.com/i/b9fe71c30e20e3179bcce31ed5509c4d) 可以把一张插画变成会眨眼、说话、转头的 2D 数字人,而它的 native 运行时提供了一套面向 C 语言的 FFI 接口(`mesh_avatar.h`),让你在自己的 C/C++ 程序里直接驱动这个数字人:播放动作、切换表情、驱动口

gitblog_00640的博客 463

DC竞赛 国能日新功率预测题 rank21 解决方案(适合新手)

DataCastle国能日新光伏功率预测 数据异常处 本题在测试集中提供了时间、辐照度、风速、风向、温度、压强、湿度、实发辐照度8个特征,以及标签**实际功率**。 而在训练集中只有前七个特征,无实发辐照度。 策略 在观察了数据之后,我们确定实发辐照度是一个强力特征,于是我们采取了stacking的策略: 1. 第一次训练以实发辐照度为标签,预测 测试集的实发辐照度 2....

yyhhlancelot的博客 7294

【数据结构初阶】——第八节.优先级队列(小根堆的模拟实现)

今天我们将进入到有关堆的有关内容的学习,以及有关优先级队列的相关使用,要对堆的概念,性质,操作有很熟悉的认识和了解,接下来就让我们进入到今天的学习当中吧!!!!!!

未央的博客哟 6263

混合部署 操作系统混合部署

在openEuler Embedded 22.03中,已经集成了OpenAMP相关支持,并与openEuler的SIG Zephyr合作实现了openEuler Embedded与实时操作系统Zephyr在QEMU平台上的混合部署。具体的混合部署方式取决于设备的硬件和软件支持。例如,可以使用虚拟机软件(如VirtualBox)在Linux操作系统上运行Android虚拟机,从而实现Linux和Android的混合部署。需要注意的是,混合部署涉及到设备的硬件和软件兼容性,以及操作系统的配置和管理。

dianqicyuyan的博客 1763

MacOS M芯片部署ComfyUI:从环境排雷到插件生态一站式指南

本文为MacOS M系列芯片用户提供了一份详尽的ComfyUI部署指南。文章深入剖析了因架构差异导致的常见安装报错根源,并给出了基于MPS后端的正确PyTorch安装命令。从创建纯净Python虚拟环境、分步安装依赖,到验证GPU加速,手把手指导完成部署。同时,还推荐了包括管理器、汉化在内的必备插件,以完善使用生态,帮助用户一站式解决从环境搭建到效率提升的所有问题。

weixin_29261711的博客 993

优先级队列(大根堆与小根堆)

优先级队列(PriorityQueue)其实就是所谓的堆,堆是一颗完全二叉树下的一种形态。存储数据在堆中为何是完全二叉树呢?是这样的,使用完全二叉树时可以避免空间的浪费,这也是堆的存储模式特别之处,如果是一些不连续的数组,采用顺序表存储更好。堆的使用:这是最简单的创建一个堆,我们可以看见,堆的特别之处是可以用于排序,所以对于排序的几种方法中,就有堆排序这种方案,Java中提供的默认堆是大根堆。堆分为两种,大根堆和小根堆。

闲来垂钓碧溪上的博客 4002

AI 小说生成器本地部署完全指南

这篇文章介绍了本地部署AI小说生成器的完整指南,主要面向网文作者、内容创作者和AI爱好者。文章从环境搭建到创作实践,详细讲解了三种主流部署方案:Ollama(推荐新手)、LMStudio(图形界面)和text-generation-webui(高级定制)。内容涵盖硬件需求、系统架构、模型选择、API对接、提示词工程等关键技术环节,并提供了小说创作的特制提示词模板和参数调优建议。文章还讨论了长篇小说管理、多模型协作等进阶技巧,以及版权伦理等法律问题。最后推荐了相关工具资源和社区论坛,帮助读者实现安全、高效、可

珂珂可爱多 2251

堆的知识点总结

数据结构堆的总结

shianla的博客 2673

自学 ABAP 和自学 SAP 的差别

有朋友在我的 ABAP 学习教程里留言: > 自学SAP是不是都要搭建虚拟服务器,然后自己去官网下载新版本SAP就可以吗 对于初学者,我们要搞清楚 ABAP 和 SAP 的区别。 ABAP 是一门编程语言,SAP 首先是德国软件公司的名称,也代表这家公司开发的一系列软件。SAP 公司开发的软件,我们有时也称产品,其功能能满足客户一个或者多个领域的业务需求。这些不同领域,我们也称为不同的业务模块,比如 ERP,CRM,SRM,HR 等等。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 6862

鸿宇多用户商城user.php RCE漏洞复现

鸿宇多用户商城 user.php 存在任意命令执行漏洞,攻击者可通过该漏洞在服务器端任意执行代码,写入后门,获取服务器权限,进而控制整个web服务器。

0xSec 1622

堆(大根堆、小根堆)

大根堆:对于任意节点 i,节点 i 的值不小于它的任何子节点的值,即父节点的值大于或等于子节点的值。它使用了数组来实现:从零开始计数,对于所有的 k ,都有 heap [k] >= heap [2k+1] 和 heap [k] >= heap [2k+2]小根堆:对于任意节点 i,节点 i 的值不大于它的任何子节点的值,即父节点的值小于或等于子节点的值。

Kayla_Smith的博客 2939

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain&#39;s apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = &quot;R. B. Palm&quot;, title = &quot;Prediction as a candidate for learning deep hierarchical models of data&quot;, year = &quot;2012&quot;,}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath(&#39;DeepLearnToolbox&#39;));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand(&#39;state&#39;,0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W&#39;); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand(&#39;state&#39;,0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = &#39;sigm&#39;;%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er &lt; 0.10, &#39;Too big error&#39;);```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand(&#39;state&#39;,0)sae = saesetup([784 100]);sae.ae{1}.activation_function = &#39;sigm&#39;;sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)&#39;)% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;;nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er &lt; 0.16, &#39;Too big error&#39;);```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x&#39;,28,28,60000))/255;test_x = double(reshape(test_x&#39;,28,28,10000))/255;train_y = double(train_y&#39;);test_y = double(test_y&#39;);%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you&#39;ll get around 1.2% errorrand(&#39;state&#39;,0)cnn.layers = { struct(&#39;type&#39;, &#39;i&#39;) %input layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 6, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %sub sampling layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 12, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er&lt;0.12, &#39;Too big error&#39;);```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er &lt; 0.08, &#39;Too big error&#39;);%% ex2 neural net with L2 weight decayrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er &lt; 0.1, &#39;Too big error&#39;);%% ex3 neural net with dropoutrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er &lt; 0.1, &#39;Too big error&#39;);%% ex4 neural net with sigmoid activation functionrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er &lt; 0.1, &#39;Too big error&#39;);%% ex5 plotting functionalityrand(&#39;state&#39;,0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = &#39;softmax&#39;; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er &lt; 0.1, &#39;Too big error&#39;);%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand(&#39;state&#39;,0)nn = nnsetup([784 20 10]); nn.output = &#39;softmax&#39;; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er &lt; 0.1, &#39;Too big error&#39;);```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free &quot;Bitdeli Badge&quot;)

堆排序(大根堆与小根堆)

是一种适用于关键字较多的情况下的排序算法,例如在十亿个数中选出前1000个最大值或者最小值 如果在传统的排序算法中(例如冒泡,插入等),我们习惯把目标数据整体进行一次排序,再截取出前1000个最小的或者最大的。 但是我们可以设想一下,从一开始我们目标就只要1000个,那么其实其余九亿九千九百九十九万九千个数据,我们压根不需要知道它们的排序顺序,只需要知道它们都比我们1000个目标数据中最大值都要大就可以了 这就是堆排序。它的思想整体上非常清晰简单,结构上是一个完全二叉树。 根结点比左右孩子都大则叫做大根堆。

whiteBearClimb的博客 1万+

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

堆——神奇的优先队列 大根堆小根堆详解,附小根堆C++代码实现与STL相关

文章目录前置知识堆操作小根堆插入代码实现小根堆删除代码实现测试代码STL实现——priority_queue1.使用2.创建3.成员函数 前置知识 堆是一个完全二叉树(最后一层可以不满,上面的每一层都是满的。一个结点若只有一个孩子结点,那一定是它的左孩子。如下图)这是一个逻辑上基于完全二叉树、物理上一般基于线性数据结构(如数组、向量、链表等)的一种数据结构。 完全二叉树最重要的性质:如果n个节点的完全二叉树的节点按照层次并按从左到右的顺序从0开始编号,对于人一个绩点都有: 序号为0的节点是根 对

哇咔咔的博客 8952

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

数据结构——【堆】

堆

m0_69323023的博客 8919

介绍大根堆&小根堆

堆的本质是“完全二叉树”(除最后一层外,每一层节点数均满;类型核心规则(父子节点关系)关键特征小根堆(Min-Heap)任意父节点的值≤其左右子节点的值整个堆的最小值一定在根节点大根堆(Max-Heap)任意父节点的值≥其左右子节点的值整个堆的最大值一定在根节点小根堆和大根堆是“完全二叉树+固定父子优先级”的结合,核心价值是O(1)获取极值、O(log n)插入/删除,效率远高于数组(O(n)查找极值);

青鱼入云的博客 2482

小根堆创建,插入,删除,排序等操作图解

堆:是用数组实现的完全二叉树,没有使用指针,根据数组的下标进行构建堆 eg:parentIndex = i;—》 leftIndex = 2i+1;rightIndex = 2i+2; 堆的分类:大根堆,小根堆。大根堆的每个子树,根节点是整个树中最大的数据,每个节点的数据都比其子节点大 小根堆的根节点数据是最小的数据,每个节点的数据都比其子节点小 注意:堆的根节点中存放的是最大或者最小元素,但是...

Zj_boring的博客 5万+

【数据结构】堆排序

整体思路:把一个序列调整为大根堆的形式,每次取堆顶元素(把堆顶元素与序列最后一个元素互换),再对新的堆顶进行调整,使满足大根堆的条件,重复上述操作,直到每个元素都被取出,可以得到一个有序的序列。

2202_75462083的博客 1283

数据结构--大根堆小根堆

堆是一种优先级队列实现,通常用于高效地找出最值(最大或最小值)。堆的每个父节点都和其子节点满足一定的关系。是堆调整操作的核心,用来维护堆的性质。是堆(Heap)数据结构的两种类型,它们都是。个元素,这些元素在数组中的索引是从。堆可以使用数组来实现,这是由于堆的。假设堆中某个节点位于数组的索引。最小堆(又称:小根堆,小顶堆)最大堆(又称:大根堆,大顶堆)结构具备的特性使得它可以。映射到一个一维数组中。

分享技术,分享经验 2967

堆的概念和创建、插入和删除操作

堆是什么 这里的堆不是用于保存动态分配对象的堆(与栈对应),即不是内存中的一块区域,而是一种数据结构。 如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元素按完全二叉树的顺序存储方式 存储 在一个一维数组中,并满足: 则 称为 小堆(或大堆)。将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。 堆在逻辑概念上是一颗完全二叉树,父子结点之间有顺序;物理概念上是一个一维的有序数组 堆的创建 将一个普通无序数组编程 ...

weixin_44468538的博客 692

C++(数据结构与算法):41---优先级队列的实现(大根堆、小根堆)

一、大根树、小根树 大根树:其中每个节点的值都大于或等于其子节点的值 小根树:其中每个节点的值都小于或等于其子节点的值 图例 二、大根堆、小根堆 大根堆:属于大根树的一种,但是必须是完全二叉树 小根堆:属于小根树的一种,但是必须是完全二叉树 图例 下面是两个大根堆,因为每个节点的值都大于其子节点的值,并且是完全二叉树 下面不是大根堆,因为其不是完全二叉树 下面是两个小...

董哥的黑板报 2067
上一篇: 【算法&数据结构体系篇class05】partition、荷兰国旗、快速排序
下一篇: 【算法&数据结构体系篇class07】:加强堆
studyday1
博客等级 码龄9年 6454粉丝 255原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值