首页 > 其他分享 >优先队列(基于二叉树的堆)

优先队列(基于二叉树的堆)

时间:2023-07-15 10:13:05浏览次数:181  
标签:优先 队列 元素 j1 Len int 二叉树 Interface interface

代码出处

Go SDK container/heap/heap.go

Interface 接口定义

type Interface interface {
   sort.Interface
   Push(x interface{}) // add x as element Len()
   Pop() interface{}   // remove and return element Len() - 1.
}

sort.Interface是自定义排序时需要实现的接口。
type Interface interface {
   // Len is the number of elements in the collection.
   Len() int
   // Less reports whether the element with
   // index i should sort before the element with index j.
   Less(i, j int) bool
   // Swap swaps the elements with indexes i and j.
   Swap(i, j int)
}

初始化堆

func Init(h Interface) {
   n := h.Len()
   for i := n/2; i >= 0; i-- { // 从第一个非叶子节点开始,遍历节点时从下往上
      down(h, i, n) // 从上往下调整
   }
}

添加元素

func Push(h Interface, x interface{}) {
   h.Push(x) // 添加元素
   up(h, h.Len()-1) // 从下往上调整
}

删除元素(取堆顶)

func Pop(h Interface) interface{} {
   n := h.Len() - 1
   h.Swap(0, n) // 将堆顶元素与最后一个元素交换
   down(h, 0, n) // 自上往下调整
   return h.Pop() // 删除堆顶元素
}

根据索引来删除某个元素

func Remove(h Interface, i int) interface{} {
   n := h.Len() - 1
   // 如果删除的元素是最后一个元素,那么直接删除
   if n != i { // 如果删除的元素不是最后一个元素,那么交换元素后调整,再删除
      h.Swap(i, n) // 将删除的元素与最后一个元素交换
      if !down(h, i, n) { // 如果从上往下调整后,i 处位置元素未动,那么说明需要从下往上调整
         up(h, i)
      }
   }
   return h.Pop() // 删除最后一个元素
}

修改元素值后调整堆

func Fix(h Interface, i int) {
   if !down(h, i, h.Len()) { // 如果从上往下调整后,i 处位置元素未动,那么说明需要从下往上调整
      up(h, i)
   }
}

从下往上调整堆

func up(h Interface, j int) {
   for {
      i := (j - 1) / 2 // parent
      if i == j || !h.Less(j, i) { // 如果 Less 函数返回 false,那么说明不满足交换条件
         break
      }
      h.Swap(i, j) // 交换父子元素
      j = i
   }
}

从上往下调整堆

func down(h Interface, i0, n int) bool {
   i := i0
   for {
      j1 := 2*i + 1 // 左孩子
      if j1 >= n || j1 < 0 { // j1 < 0 after int overflow
         break
      }
      j := j1 // left child
      if j2 := j1 + 1; j2 < n && h.Less(j2, j1) {
         j = j2 // = 2*i + 2  // right child
      }
      if !h.Less(j, i) { // 如果不满足交换条件,那么结束
         break
      }
      h.Swap(i, j) // // 交换父子元素
      i = j
   }
   return i > i0 // 如果是 true,那么说明交换过;否则,说明没有交换过
}

 

标签:优先,队列,元素,j1,Len,int,二叉树,Interface,interface
From: https://www.cnblogs.com/WJQ2017/p/17555638.html

相关文章

  • 2023.7.14 在二叉树中分配硬币
    借用灵神的图:所以一个直观的想法就是,计算这个子树的硬币个数和节点个数的差的绝对值。这个就是需要传递给父结点的硬币数量。如果这个子树中的子结点也全部执行了这个操作,那么就会把硬币全部集中到当前结点,因此不用考虑子结点中的移动。所以这是个递归算法。(因为要先完成子结......
  • rabbitMQ死信队列和延迟交换机
    一、死信队列(deadLetters)1.死信产生的三种方式(1)消息被消费者拒绝,requeue设置为false message在正常传输中消费者执行了nack或者reject且requeue变为false则将该message存储到死信交换机,再送入死信队列,重新被其他的消费者消费 (2)消息的TTL到期消息的TimeToLive生......
  • java代码向stream消息队列发送消息失败
    如何实现Java代码向Stream消息队列发送消息失败作为一名经验丰富的开发者,您可以教会刚入行的小白如何实现Java代码向Stream消息队列发送消息失败。本文将按照以下流程展示步骤,并提供相应的代码和注释。流程图以下是实现该功能的整体流程图:步骤动作1.创建Stream连接......
  • STM32:rtthread_消息队列
    1消息队列  消息队列是一种常用的线程间异步通讯方式;   消息队列能够接收来自线程或中断中不固定长度的消息,并把消息缓存在自己的内存空间中,供线程间进行异步通讯;  1.1结构体定义//rtconfig.h源码默认注释掉未开启,用到消息队列的时候需要自己开启;#defineRT_USI......
  • 算法学习day14二叉树part01-94、144、145
    packageSecondBrush.Tree;importjava.util.ArrayList;importjava.util.List;/***94.二叉树的中序遍历*给定一个二叉树的根节点root,返回它的中序遍历。**/publicclassBinaryTreeInorderTraversal_94{publicList<Integer>inorderTraversal(Tre......
  • 单调栈与单调队列优化 dp
    单调栈将一个元素插入单调栈时,为了维护栈的单调性,需要在保证将该元素插入到栈顶后整个栈满足单调性的前提下弹出最少的元素。例如,栈中自顶向下的元素为\(\{0,11,45,81\}\)。插入元素\(14\)时为了保证单调性需要依次弹出元素\(0,11\),操作后栈变为\(\{14,45,81\}\)。模板......
  • LeetCode 剑指 Offer 08. 二叉树的下一个节点
    题目:二叉树的下一个节点给定一棵二叉树的其中一个节点,请找出中序遍历序列的下一个节点。(树的后继)注意:如果给定的节点是中序遍历序列的最后一个,则返回空节点;二叉树一定不为空,且给定的节点一定不是空节点;解题思路二叉树的中序遍历:{[左子树],根节点,[右子树]}如图所示......
  • PHP+Redis消息队列
    调用方式$redis=RedisManager::getInstance();$queue=json_encode(['queue_id'=>$queueId,'question'=>$question],256);if($redis->LPush('QA_wecom',$queue))returnResult::Success();单例<?phpnamespaceapp\admin\com......
  • 广度优先搜索(BFS)
    广度优先搜索(BFS)点亮所有的灯BFS的方法非连通图的广度优先遍历算法实现按广度优先搜索遍历连通图GBFS算法效率分析DFS和BFS算法效率比较空间复杂度相同,都是O(n)(借助栈和队列)时间复杂度与储存结构(邻接矩阵或邻接表)有关,而与搜索路径无关.......
  • 【数据结构与算法】队列算法题
    TS实现队列interfaceIQueue<T>{//入队enqueue(item:T):void;//出队dequeue():T|undefined;//队首peek():T|undefined;//是否为空isEmpty():boolean;//大小size():number;}classArrayQueue<T>implementsIQueue<T>{......