最大优先队列的实现(思路分析) [数据结构与算法]

最大优先队列的实现(思路分析)

我们要分析如何实现最大优先队列, 我们首先要明确我们是通过堆来实现最大优先队列的

添加元素的操作:

我们每次插入一个元素到堆中的最后一个位置, 然后使用一个上浮算法就可以了

  • 就是让某个位置的元素上浮到应该存在的合理位置

  • 那么这个上浮算法要如何实现?

    • 我们从第k个元素位置(也就是我们要上浮的元素的位置)开始判断, 判断它和父节点的值谁更加大 , 如果第k个元素位置的值更加大, 则交换两个位置的值, 然后一直判断, 知道判断到k不满足大于父节点的条件即可, 或者如果最终k的值一直比父节点大, 那么最后一次应该是和根节点进行一个比较, 也就是当k的值刚刚是大于1的最小的两个父节点的取值的时候, 也就是是2或者3的时候, 这个时候我们叫要判断完之后就退出循环, 也就是只要是k>1就一直比较, 直到比较到k的父节点就是根节点为止
      • 我们此时实现最大优先队列的时候是从索引为1位置开始存储值的, 因为从1位置开始存储元素时, 我们计算某个结点的父节点时, 直接就是n/2, 效率会更加高一些
        • 如果是从索引为0的位置开始存储元素的话, 我们要计算某个结点的父节点时就是(n-1)/2
        • 所以我们其实就相当于牺牲了一个空间来换取效率

出队操作:

其实就是删除堆中值最大的结点, 也就是大顶堆的根节点

  • 我们删除堆中的元素的时候, 如果是直接删除头结点是很耗费时间的, 因为我们的堆结构是使用数组来实现的, 所以也就是如果我们要删除头结点元素的时候, 此时头结点是在索引为1处, 这个时候我们如果将头结点位置的值删除掉之后, 也就是将索引为1处的值置空, 然后我们此时为了有新的头结点顶替, 这个时候我们就要让所有后面的值向前移动一个单位, 这个时候就是很消耗时间的, 并且这个时候我们原本是一个大顶堆, 但是全体元素向前移动一个单位之后结构就可能遭到破坏 —> 因为我们的大顶堆只是某个元素比左右子节点的值都大, 但是左右子节点的值却是不确定谁大的, 所以如果要前移我们要判断左右子节点谁大, 谁大就要谁移动到前面

    • 所以我们就选择另一种方式来出队, 就和堆排序的时候的操作是一样的, 在我们的大顶堆中, 如果我们要删除最大值结点, 也就是删除根结点, 这个时候我们先使用根结点和最后一个位置的值进行一个值交换, 然后直接将我们的记录数组中有效元素个数的变量减一即可, 然后将这个最大元素出队之后我们要注意, 此时我们将数组中的最后一个元素放到了第一个位置上, 所以可能就会破坏大顶堆结构, 这个时候我们就执行一个下沉算法, 这样我们就能让堆重新变为有序

      • 那么我们的下沉算法要如何实现?

        • 我们开始的时候就从第k个位置开始, 我们先找到k位置的左子节点和右子节点中值较大的 ,然后使用我们k位置的值和较大值进行一个比较, 如果k位置的值小于子节点中的较大值, 则就要进行一个值的交换, 一直交换到第k个位置的值不小于两个子节点中的较大值为止,或者一直遍历到没有子节点为止
          • 那么我们如何判断一个结点没有子节点?
          • 注意: 我们的堆中的元素存储一定是满足完全二叉树条件的, 也就是最后一个有子节点的结点一定是有左子节点的, 如果遍历到某个结点的时候这个结点连左子节点都没有, 那么肯定肯定是没有子节点的

你可能感兴趣的:(算法与数据结构,算法,数据结构,java)