【数据结构与算法】第五章 优先队列(堆)排序

第五章 优先队列(堆)排序

优先队列是对Queue的一种优化方案。

java标准库中实现Queue的是LinkedList.它只能解决先进先出的排队操作。它是按入队时间的先后顺序进行存储。而优先队列是按优先级的顺序进行存储。

在现实生活中也很常见,比如火车站买票,军人优先、有特殊情况的客人优先。也就是说不按你的时间顺序,而是客人的优先级别。

 

优先队列,也就可以称为最大堆或最小堆,具体看我们的实现。java标准库java.util.PriortyQueue实现的是最小堆。 

一、基本结构

 

它是一种完全二叉树,可以不是满的二叉树,但如果不满,只能是最后一层最从左往右,不能跳节点。

 

二叉堆,我们所说的二叉堆,有两个特性,

1)父节点大于等于它的子节点。

2)它是一个最大堆。(不过我们也可以做出来个最小堆)

3)节点的大小,和它所处是的层给是没有联系的。

 

二、具体实现

我们先现,用数据可以很好的表示二叉堆的数据结构。

如果从0开始,也可以这么表示:

 

 

  • //以0为根,左节点索引位置

private int leftChild(int index) {

    return 2 * index + 1;

}

 

  • //以0为根,右节点索引位置

private int rightChild(int index) {

    return 2 * index + 2;

}

 

  • //得到父节点的索引位置

private int parent(int index) {

    if (index == 0) {

        return 0;

    } else {

        return (index - 1) / 2;

    }

}

1、添加一个节点(元素上浮操作)

 

1)按newVal插入到最后一个索引位置。

2)size ++

2)依次和它的父节点进行比较。如果小于父节点的值,那么进行值交换。直到根节点的位置索引位置。

 

代码如下:

public void add(T value) {

    data.add(data.size(), value);

    siftUp(data.size() - 1);

}

 

//上浮操作

private void siftUp(int index) {

    while (index > 0) {

        T parentVal = data.get(parent(index));

        T currentVal = data.get(index);

        if (currentVal.compareTo(parentVal) < 0) {

            data.swap(index, parent(index));

        } else {

            break;

        }

        index = parent(index);

    }

}

2、删除最小元素

1)先最后的索引位置元素的值,赋值给根节点(索引为0的位置)。【不是删除根节点,是值的覆盖】

2)size -- 也没有把最后一个索引位置的元素删除。只是size上面不进行关联,再也找不到这个索引位置而已

3)从根节点开始进行下浮。

4)依次进行:节点的值与左右子节点中最小值进行比较,如果左右子节点中最小值小于该节点的值,则进行下浮操作。交互元素的值。直到叶子节点为止。

 

代码如下:

public T remove() {

    if (data.isEmpty()) {

        return null;

    }

    T popVal = data.get(0);

    data.swap(0, data.size() - 1);

    data.remove(data.size() - 1);

    siftDown(0);

    return popVal;

}

 

private void siftDown(int k) {

    while (leftChild(k) < data.size()) {

        int j = leftChild(k);

        if (j + 1 < data.size() && data.get(j + 1).compareTo(data.get(j)) < 0) {

            j++;

        }

        if (data.get(k).compareTo(data.get(j)) < 0) {

            break;

        }

        data.swap(k, j);

        k = j;

    }

}

 

 

三、构造一个优先队列

一个普通数组变成优先队列的过程如下:

public MyPriorityQueue(T[] arr) {

    this.data = new MyArrayList<T>(arr);

    for (int i = parent(data.size() - 1); i >= 0; i--) {

        siftDown(i);

    }

}

 

四、排序实现

放到第六章排序中实现

 

PriorityQueue<Integer> minHeap = new PriorityQueue<Integer>(); //小顶堆,默认容量为11

PriorityQueue<Integer> maxHeap = new PriorityQueue<Integer>(11,new Comparator<Integer>(){ //大顶堆,容量11

    @Override

    public int compare(Integer i1,Integer i2){

        return i2-i1;

    }

});

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值