了解优先级队列(堆)

news/2024/5/20 9:18:04 标签: 队列, , 优先级队列

优先级队列

的定义

把所有元素按照完全二叉树的顺序存储方式存储。
逻辑上是一个完全二叉树,实质上是一个顺序表
在这里插入图片描述
将元素放入数组中,可以根据二叉树的性质将其还原:
假设数组下标为i,
如果i为0,代表根节点
其双亲节点为 (i -1 ) / 2

大小

将根节点最大的叫大,根节点最小的叫小

  • 中的某个结点值,总是不大于或者不小于其父节点的值
  • 总是一颗完全二叉树

根据有序数组,我们可以推出它是,但是根据不可以推出它有序。

的创建

向下调整

前提:是完全二叉树,并且只有一个位置破坏了的性质,其余位置满足太条件。
例如:在这里插入图片描述
上图中,只有27不满足,我们需要将更节点向下调整。

思路:index表示需要调整的位置,

  1. 判断index是否为叶子结点,如果是本次调整结束
  2. 取index中两个孩子最小元素
  3. 如果比最小元素小,调整结束,否则交换位置
  4. 将index置位最小元素下标,在此判断是否需要向下调整。

代码实现:

    public static void heapify(int[] array, int size, int index) {
        while (true) {
            int leftIndex = 2 * index + 1;
            if (leftIndex >= size) {
                return;
            }
            int minIndex = leftIndex;
            int rightIndex = leftIndex + 1;
            if (rightIndex < size && array[rightIndex] < array[leftIndex]) {
                minIndex = rightIndex;
            }
            if (array[minIndex] >= array[index]) {
                return;
            }
            int t = array[index];
            array[index] = array[minIndex];
            array[minIndex] = t;

            index = minIndex;
        }
    }

给定一个数字,给定有效数据个数,我们将其变成一个
思路:
我们找到倒数第一个非叶子节点,然后从其位置向头结点一直向下调整,如图:
在这里插入图片描述
代码实现:

    public static void createHeap(int[] array, int size) {
        //最后一个结点为size-1,,最后一个非叶子结点为(size-1-1)/2
        int last = (size - 2) / 2;
        for (int i = last; i >= 0; i--) {
            //向下取整
            heapify(array, size, i);
        }
    }

优先级队列

Java 中给我们提供了PriorityQueue的优先级队列(小),

函数名功能
Boolean add()插入
E remove()删除
E element查看顶元素

PriorityQueue是小,但是我们想让他返回其最大的元素,那么我们需要自己定义比较器:

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

public class PriorityQueueDemo {
    static class IntegerComparator implements Comparator<Integer> {
        //返回较大的
        @Override
        public int compare(Integer o1, Integer o2) {
            return -o1.compareTo(o2);
        }
    }

    public static void main(String[] args) {
        Comparator<Integer> comparator = new IntegerComparator();
        System.out.println(comparator.compare(8, 2));   // < 0
        
        Queue<Integer> queue = new PriorityQueue<>(comparator);

        queue.add(9);
        queue.add(5);
        queue.add(2);
        queue.add(7);

        System.out.println(queue.element());
    }
}

模拟实现优先级队列

插入: 尾插,然后向上调整。
删除:头尾交换,向下调整。
查看:直接看第一个元素。

public class MyPriorityQueue {
    //不考虑扩容
    private String[] array = new String[1000];
    private int size = 0;

    public void add(String e) {
        //尾插,然后向上调整
        array[size++] = e;
        shiftUP(size - 1);

    }

    private void shiftUP(int index) {
        while (true) {
            if (index == 0) {
                return;
            }
            int parentIndex = (index - 1) / 2;
            int cmp = array[parentIndex].compareTo(array[index]);
            if (cmp <= 0) {
                return;
            }
            String t = array[index];
            array[index] = array[parentIndex];
            array[parentIndex] = t;

            index = parentIndex;
        }
    }

    public String remove() {
        //将首元素拿出来,并将最后一个元素放在队首,然后向下调整。
        String s = array[0];
        array[0] = array[size - 1];
        size--;
        shiftDown(0);
        return s;
    }

    private void shiftDown(int index) {
        int cmp;
        while (2 * index + 1 < size) {
            int minIndex = 2 * index + 1;
            if (minIndex + 1 < size) {
                cmp = array[minIndex + 1].compareTo(array[minIndex]);
                if (cmp < 0) {
                    minIndex++;
                }
            }
            cmp = array[index].compareTo(array[minIndex]);
            if (cmp <= 0) {
                return;
            }
            String t = array[index];
            array[index] = array[minIndex];
            array[minIndex] = t;
            index = minIndex;

        }
    }

    public String element() {
        return array[0];
    }
}

TOPK问题

关于topK问题,我们需要记住
找前k个最大的,建k个大小的小
找前k个最小的,建k个大小的大


http://www.niftyadmin.cn/n/1530244.html

相关文章

查找和最小的k对数字

查找和最小的k对数字查找和最小的k对数字查找和最小的k对数字 LeetCode373&#xff1a; 链接&#xff1a;查找和最小的k对数字 题目描述&#xff1a; 373. 查找和最小的K对数字 给定两个以升序排列的整形数组 nums1 和 nums2, 以及一个整数 k。 定义一对值 (u,v)&#xff0c;…

排序算法原理及实现

排序算法原理及实现插入排序原理&#xff1a;实现&#xff1a;希尔排序原理&#xff1a;实现&#xff1a;选择排序原理&#xff1a;实现&#xff1a;冒泡排序原理&#xff1a;实现&#xff1a;堆排序原理&#xff1a;实现&#xff1a;快速排序归并排序排序算法的性能分析排序&a…

快速排序——一看就会,一写就废

快速排序原理&#xff1a;实现&#xff1a;partitionhoare法&#xff1a;实现&#xff1a;挖坑法&#xff1a;实现&#xff1a;前后遍历&#xff1a;实现&#xff1a;非递归实现&#xff1a;原理&#xff1a; 1、从待排序区间中选择一个数&#xff0c;作为基准值&#xff08;p…

归并排序(重要)

归并排序原理&#xff1a;分解&#xff1a;合并&#xff1a;非递归&#xff1a;原理&#xff1a; 归并排序&#xff08;mergeSort&#xff09;是建立在归并操作上的一种有效的排序算法&#xff0c;该算法采用分治法。将以有序的子序列合并&#xff0c;得到一个完全有序的序列&…

排序算法性能分析和海量数据排序问题

排序算法性能分析时间和空间复杂度快速排序的优化海量数据排序问题&#xff1a;时间和空间复杂度 整理&#xff1a; 排序稳定性时间复杂度空间度复杂度最好最坏最好/平均/最坏最好/平均/最坏冒泡排序有序逆序稳定O(n) / O(n2) / O(n2)O(1)插入排序有序逆序稳定O(n) / O(n2) /…

二叉搜索树原理及操作

二叉搜索树原理构建二叉搜索树查找插入删除原理 二叉搜索树&#xff08;Binary Search Tree BST&#xff09; 又称为二叉排序树&#xff0c;它是一颗空树或者具有以下性质&#xff1a; 它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值它的右子树不为空&…

模拟实现HashMap

模拟实现HashMap模拟实现HashMap注意事项关于Set和Map区别&#xff1a;见链接&#xff1a; Set和Map 关于HashTable 见链接&#xff1a; 哈希表 模拟实现HashMap Node&#xff1a; public class Node {public String key;public Integer value;public Node next;public Nod…

SQL查询总结

查询聚合查询聚合函数GROUP BY 子句多次分组聚合HAVING联合查询内连接外连接自连接子查询[NOT] IN[NOT] EXISTSSQL基础语句查询为&#xff1a;SELECT * FROM student;聚合查询 聚合函数 常见的聚合函数有&#xff1a;MAX、MIN、AVG、COUNT、SUM 函数说明COUNT返回查询到数据…