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

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

我们知道优先队列其实内部实现就是一个堆的数据结构,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 queue = new PriorityQueue<>();///优先队列默认的小根堆
    void solve()
    {
        queue.add(5);
        queue.add(3);
        queue.add(56);
        while(!queue.isEmpty())
        {
            System.out.println(queue.poll());///维护一个堆保证每次取出的都是最小的并出堆
        }
        Comparator cmp;///可以new一个重载器;
        cmp = new Comparator()
        {
            public int compare(Integer e1,Integer e2)
            {
                return e2 - e1;///重载优先级使其变为大根堆
            }
        };
        Queue 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 dogcmp;
        dogcmp = new Comparator() {
            @Override
            public int compare(Dog o1, Dog o2) {
                return o1.x-o2.x;///重载优先级使其变为小根堆
            }
        };
        Queue q = new PriorityQueue(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();
    }
}

你可能感兴趣的:(数据结构)