浅谈堆以及java优先队列的详细使用

来源:互联网 发布:h5能打开淘宝app吗 编辑:程序博客网 时间:2024/06/06 16:26

最近在学习集合框架整理下感觉有用的东西。

我们知道优先队列其实内部实现就是一个堆的数据结构,java默认的是一个小跟堆,每次取出最小的元素,因为堆的性质他可以做到O(logn)级别的插入和删除操作。

我们知道堆的性质是有:
1.堆中某个结点的值总是不大于(或不小于)其父结点的值;
2.堆总是一棵完全二叉树。

将根结点最大的堆叫做大根堆,根结点最小的堆叫做小根堆。常见的堆有二叉堆、斐波那契堆等

插入:向堆中插入一个新元素;在数组的最末尾插入新结点。然后自下而上调整子结点与父结点:比较当前结点与父结点,不满足堆性质则交换,使得当前子树满足二叉堆的性质。时间复杂度为 O(logn)。

弹出:删除堆顶元素,再把堆存储的最后那个结点填在根结点处。再从上而下调整父结点与它的子结点。时间复杂度为 O(logn)。

删除:使该元素与堆尾元素交换,调整堆容量,再由原堆尾元素的当前位置自顶向下调整。时间复杂度为 O(logn)。

如果经常需要合并两个堆的操作,那么使用二项堆、斜堆、左偏树等数据结构会更好。
可并堆支持合并操作,使得合并后的堆也能保持堆的性质。左偏树是可并堆的一种,保证左子树的深度大于右子树的深度,再用右子树与另一个堆合并。
因此,堆支持查询最值、插入、删除操作。

堆排序,通过堆维护最值,对最值逐个弹出,使得得到的序列有序。
下面看下一般的堆我们都直接用优先队列实现如下

import java.io.BufferedInputStream;import java.util.Comparator;import java.util.PriorityQueue;import java.util.Queue;import java.util.Scanner;class Dog{    public int x;}public class Main{    Scanner cin = new Scanner(new BufferedInputStream(System.in));    Queue<Integer> queue = new PriorityQueue<>();///优先队列默认的小根堆    void solve()    {        queue.add(5);        queue.add(3);        queue.add(56);        while(!queue.isEmpty())        {            System.out.println(queue.poll());///维护一个堆保证每次取出的都是最小的并出堆        }        Comparator<Integer> cmp;///可以new一个重载器;        cmp = new Comparator<Integer>()        {            public int compare(Integer e1,Integer e2)            {                return e2 - e1;///重载优先级使其变为大根堆            }        };        Queue<Integer> que = new PriorityQueue<>(cmp);///筛入一个重载器使其变为大跟堆        que.add(5);        que.add(6);        que.add(7);        que.add(1);        que.add(11);        System.out.println("*****");        while(!que.isEmpty())        {            System.out.println(que.poll());///维护一个堆保证每次取出的都是最大的并出堆        }        Comparator<Dog> dogcmp;        dogcmp = new Comparator<Dog>() {            @Override            public int compare(Dog o1, Dog o2) {                return o1.x-o2.x;///重载优先级使其变为小根堆            }        };        Queue<Dog> q = new PriorityQueue<Dog>(dogcmp);        Dog g = new Dog();        g.x = 1;        Dog g1 = new Dog();        g1.x = 100;        Dog g2 = new Dog();        g2.x = 50;        Dog g3 = new Dog();        g3.x = 11;        q.add(g);        q.add(g1);        q.add(g2);        q.add(g3);        System.out.println("*****");        while(!q.isEmpty())        {            System.out.println(q.poll().x);///维护一个堆保证每次取出的都是最小的并出堆        }    }    public static void main(String[] args)    {        new Main().solve();    }}
原创粉丝点击