Java优先队列(堆)理解和使用

举报
海风极客 发表于 2022/10/16 17:01:45 2022/10/16
【摘要】 1 什么是优先队列(堆) 1.1 继承关系首先看下Java中堆的继承关系,可以看出堆实现了队列的全部方法。 1.2 堆的数据结构 1.3 特征:(1)二叉堆是一个完全二叉树(2)根节点总是大于左右子节点(大顶堆),或者是小于左右子节点(小顶堆)。 1.4 常见方法add() //调用了offer方法 public boolean add(E e) { return offer(e)...

1 什么是优先队列(堆)

1.1 继承关系

首先看下Java中堆的继承关系,可以看出堆实现了队列的全部方法。
在这里插入图片描述

1.2 堆的数据结构

在这里插入图片描述

1.3 特征:

(1)二叉堆是一个完全二叉树

(2)根节点总是大于左右子节点(大顶堆),或者是小于左右子节点(小顶堆)。

1.4 常见方法

在这里插入图片描述
add()

	//调用了offer方法
	public boolean add(E e) {
  	  return offer(e);
	}

    //判断输入元素是否为空,如果不为空
	public boolean offer(E e) {
        if (e == null)
            throw new NullPointerException();
        modCount++;
        int i = size;
        if (i >= queue.length)
            //增加容量
            grow(i + 1);
        size = i + 1;
        if (i == 0)
            queue[0] = e;
        else
            //上浮方法--(小根堆)将小的元素进行上浮
            siftUp(i, e);
        return true;
	}

offer()

    //判断输入元素是否为空,如果不为空
	public boolean offer(E e) {
        if (e == null)
            throw new NullPointerException();
        modCount++;
        int i = size;
        if (i >= queue.length)
            //增加容量
            grow(i + 1);
        size = i + 1;
        if (i == 0)
            queue[0] = e;
        else
            //上浮方法--(小根堆)将小的元素进行上浮
            siftUp(i, e);
        return true;
	}

    //私有方法
    /*
    作用:在k位置插入项x,通过提升x到树的顶端,保持堆不变,直到它大于或等于它的父结点,
    或者是根结点
    */
 	private void siftUp(int k, E x) {
        if (comparator != null)
            siftUpUsingComparator(k, x);
        else
            siftUpComparable(k, x);
    }

peek()

    //弹出堆顶的元素
    public E peek() {
        return (size == 0) ? null : (E) queue[0];
    }

remove()

	//先找出位置,再进行删除
	public boolean remove(Object o) {
        int i = indexOf(o);
        if (i == -1)
            return false;
        else {
            removeAt(i);
            return true;
        }
    }

contains()

	//查看元素是否存在的本质就是看看有没有他的位置
	public boolean contains(Object o) {
        return indexOf(o) != -1;
    }

toArray()

    public Object[] toArray() {
        return Arrays.copyOf(queue, size);
    }
    //与上边的不同就是需要有一个泛型
    public <T> T[] toArray(T[] a) {
        final int size = this.size;
        if (a.length < size)
            //返回一个新的带泛型的数组
            return (T[]) Arrays.copyOf(queue, size, a.getClass());
        System.arraycopy(queue, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;
    }

size()

    public int size() {
        return size;
    }

clear()

	//遍历一次 全部置为null
	public void clear() {
        modCount++;
        for (int i = 0; i < size; i++)
            queue[i] = null;
        size = 0;
    }

poll()

    //返回并删除第一个元素
    public E poll() {
        if (size == 0)
            return null;
        int s = --size;
        modCount++;
        //取出堆顶元素
        E result = (E) queue[0];
        //取出最后一个元素
        E x = (E) queue[s];
        queue[s] = null;
        if (s != 0)
            //做下沉操作
            siftDown(0, x);
        return result;
    }

2 Java中堆的使用(小根堆为例)

2.1 堆排序


/**
 * @author ymx
 */
public class TestPriorityQueue {

    /**
     * 声明一个堆
     */
    public PriorityQueue<Integer> queue = new PriorityQueue();

    /**
     * 初始化数据
     *
     * @param items
     */
    public void init(int[] items) {
        for (int i = 0; i < items.length; i++) {
            //将数据放入堆中
            queue.add(items[i]);
        }
    }

    /**
     * 排序操作
     *
     * @return
     */
    public int[] sort() {
        int[] items = new int[queue.size()];
        int i = 0;
        while (queue.size() > 0) {
            //弹出并删除堆顶元素
            items[i] = queue.poll();
            i++;
        }
        return items;
    }


    public static void main(String[] args) {
        TestPriorityQueue test = new TestPriorityQueue();
        test.init(new int[]{5, 6, 4, 3, 8, 9, 7, 1, 2});
        int[] sort = test.sort();
        System.out.print("排序结果:");
        for (Integer i : sort) {
            System.out.print(i + "  ");
        }
    }

}

运行结果:
在这里插入图片描述

2.2 进程调度

堆在操作系统的进程调度中也被广泛使用,比如依据优先级进行的进程调度等等,在这里就不做详解啦

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。