首页 > 编程语言 >开源优先队列FastPriorityQueue源码阅读

开源优先队列FastPriorityQueue源码阅读

时间:2023-03-31 20:55:51浏览次数:40  
标签:node FastPriorityQueue childRight 节点 finalQueueIndex 开源 源码 nodes QueueIndex

FastPriorityQueue

  源码连接:

https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp  

  大致结构:

  1节点在内存中的结构还是数组,且首节点为无意义节点,有效节点从索引1开始。(见FastPriorityQueue的T[] _nodes)
  2维护的节点必须时固定的继承。(见FastPriorityQueueNode)
  3该队列为非线程安全的
  4不要对不在优先级队列中的节点调用UpdatePriority(),也不要对在优先级队列的节点调用Enqueue()。
  5一个节点只能在一个queue里面,如果要迁移节点到新的队列时应该先将其从原本的queue中移除并重置自身(ResetNode函数)后再加入新queue。

  如何实现判断界定是否在容器中。

  节点FastPriorityQueueNode中维护了一个数组的索引(见FastPriorityQueueNode的QueueIndex),该索引从1开始。
时间复杂度为O(1)。

  是否支持优先级动态变,变更后,如何排序?

  支持优先级动态变。(入口见FastPriorityQueueNode的UpdatePriority)
  变更后,需要维持大顶堆的大顶,对现有节点(包含新增或者变更节点)根据优先级触发节点上浮CascadeUp或节点下沉CascadeDown。
  采用大顶堆的方式,老样子,采用位运算(<<1)方式计算堆中父节点位置,但只维持了大顶,并没有完全排序,即数组中的元素优先级不是从大到小的。
如果是内部节点动态变更优先级,比如随着节点增加,可能构造这样一棵子树:父节点优先级为8,左右子节点的优先级分别为3和5,它本身就不是完全从大到小,当优先级3的节点优先级变成9,只会让它跟父节点交换,交换后依旧不是完全从大到小。
  此外,新增一个同优先级的节点是不会把原本节点顶后,而是对新增节点进行下沉操作。(见FastPriorityQueueNode的CascadeDown)

private void CascadeUp(T node)
{
    //aka Heapify-up
    int parent;
    if(node.QueueIndex > 1)
    {
        parent = node.QueueIndex >> 1;
        T parentNode = _nodes[parent];
        if(HasHigherOrEqualPriority(parentNode, node))
            return;

        //Node has lower priority value, so move parent down the heap to make room
        _nodes[node.QueueIndex] = parentNode;
        parentNode.QueueIndex = node.QueueIndex;

        node.QueueIndex = parent;
    }
    else
    {
        return;
    }
    while(parent > 1)
    {
        parent >>= 1;
        T parentNode = _nodes[parent];
        if(HasHigherOrEqualPriority(parentNode, node))
            break;

        //Node has lower priority value, so move parent down the heap to make room
        _nodes[node.QueueIndex] = parentNode;
        parentNode.QueueIndex = node.QueueIndex;

        node.QueueIndex = parent;
    }
    _nodes[node.QueueIndex] = node;
}
private void CascadeDown(T node)
{
    //aka Heapify-down
    int finalQueueIndex = node.QueueIndex;
    int childLeftIndex = 2 * finalQueueIndex;

    // If leaf node, we're done
    if(childLeftIndex > _numNodes)
    {
        return;
    }

    // Check if the left-child is higher-priority than the current node
    int childRightIndex = childLeftIndex + 1;
    T childLeft = _nodes[childLeftIndex];
    if(HasHigherPriority(childLeft, node))
    {
        // Check if there is a right child. If not, swap and finish.
        if(childRightIndex > _numNodes)
        {
            node.QueueIndex = childLeftIndex;
            childLeft.QueueIndex = finalQueueIndex;
            _nodes[finalQueueIndex] = childLeft;
            _nodes[childLeftIndex] = node;
            return;
        }
        // Check if the left-child is higher-priority than the right-child
        T childRight = _nodes[childRightIndex];
        if(HasHigherPriority(childLeft, childRight))
        {
            // left is highest, move it up and continue
            childLeft.QueueIndex = finalQueueIndex;
            _nodes[finalQueueIndex] = childLeft;
            finalQueueIndex = childLeftIndex;
        }
        else
        {
            // right is even higher, move it up and continue
            childRight.QueueIndex = finalQueueIndex;
            _nodes[finalQueueIndex] = childRight;
            finalQueueIndex = childRightIndex;
        }
    }
    // Not swapping with left-child, does right-child exist?
    else if(childRightIndex > _numNodes)
    {
        return;
    }
    else
    {
        // Check if the right-child is higher-priority than the current node
        T childRight = _nodes[childRightIndex];
        if(HasHigherPriority(childRight, node))
        {
            childRight.QueueIndex = finalQueueIndex;
            _nodes[finalQueueIndex] = childRight;
            finalQueueIndex = childRightIndex;
        }
        // Neither child is higher-priority than current, so finish and stop.
        else
        {
            return;
        }
    }

    while(true)
    {
        childLeftIndex = 2 * finalQueueIndex;

        // If leaf node, we're done
        if(childLeftIndex > _numNodes)
        {
            node.QueueIndex = finalQueueIndex;
            _nodes[finalQueueIndex] = node;
            break;
        }

        // Check if the left-child is higher-priority than the current node
        childRightIndex = childLeftIndex + 1;
        childLeft = _nodes[childLeftIndex];
        if(HasHigherPriority(childLeft, node))
        {
            // Check if there is a right child. If not, swap and finish.
            if(childRightIndex > _numNodes)
            {
                node.QueueIndex = childLeftIndex;
                childLeft.QueueIndex = finalQueueIndex;
                _nodes[finalQueueIndex] = childLeft;
                _nodes[childLeftIndex] = node;
                break;
            }
            // Check if the left-child is higher-priority than the right-child
            T childRight = _nodes[childRightIndex];
            if(HasHigherPriority(childLeft, childRight))
            {
                // left is highest, move it up and continue
                childLeft.QueueIndex = finalQueueIndex;
                _nodes[finalQueueIndex] = childLeft;
                finalQueueIndex = childLeftIndex;
            }
            else
            {
                // right is even higher, move it up and continue
                childRight.QueueIndex = finalQueueIndex;
                _nodes[finalQueueIndex] = childRight;
                finalQueueIndex = childRightIndex;
            }
        }
        // Not swapping with left-child, does right-child exist?
        else if(childRightIndex > _numNodes)
        {
            node.QueueIndex = finalQueueIndex;
            _nodes[finalQueueIndex] = node;
            break;
        }
        else
        {
            // Check if the right-child is higher-priority than the current node
            T childRight = _nodes[childRightIndex];
            if(HasHigherPriority(childRight, node))
            {
                childRight.QueueIndex = finalQueueIndex;
                _nodes[finalQueueIndex] = childRight;
                finalQueueIndex = childRightIndex;
            }
            // Neither child is higher-priority than current, so finish and stop.
            else
            {
                node.QueueIndex = finalQueueIndex;
                _nodes[finalQueueIndex] = node;
                break;
            }
        }
    }
}

  移除节点如何实现:

  先将移除节点A和末尾节点B做个数组位置上的交换。然后对交换后的B进行大顶堆的调整,并置空尾节点。

  是否支持元素查询

  元素的查询需要自行实现。

标签:node,FastPriorityQueue,childRight,节点,finalQueueIndex,开源,源码,nodes,QueueIndex
From: https://www.cnblogs.com/lanyelinxiang/p/17277446.html

相关文章

  • Spark源码解析(二):Spark闭包检查
    一、理解Scala闭包:Closures1.1闭包的定义闭包就是一个函数和与其相关的引用环境组合的一个整体(实体)。进一步说,闭包是绑定了自由变量的函数实例。通常来讲,闭包的实现机制是定义一个特殊的数据结构,保存了函数地址指针与闭包创建时的函数的词法环境以及绑定自由变量。对于闭......
  • Spark源码解析(一):RDD之Transfrom算子
    一、延迟计算RDD代表的是分布式数据形态,因此,RDD到RDD之间的转换,本质上是数据形态上的转换(Transformations)在RDD的编程模型中,一共有两种算子,Transformations类算子和Actions类算子。开发者需要使用Transformations类算子,定义并描述数据形态的转换过程,然后调用Actions......
  • ETCD源码阅读(三)
    DAY2:阅读raftexample:etcd/contrib/raftexampleserveChannels()func(rc*raftNode)serveChannels(){ snap,err:=rc.raftStorage.Snapshot() iferr!=nil{ panic(err) } rc.confState=snap.Metadata.ConfState rc.snapshotIndex=snap.Metadata.Index r......
  • ETCD源码阅读(二)
    DAY1:阅读raftexample:etcd/contrib/raftexampleraftexample包括三个组件:一个基于raft的kvstore、一个RESTAPIServer、一个基于etcdraft实现的RaftNode。其中RaftNode也拥有一个Httpserver,用于与peer节点进行通信。RESTAPIServer则是这个RaftNode的client。kvs......
  • ETCD源码阅读(一)
    DAY0:ETCD架构下图中展示了etcd如何处理一个客户端请求涉及到的模块和流程。图中淡紫色的矩阵表示etcd,它包括如下几个模块:etcdserver:对外接受客户端的请求,请求etcd代码中的etcdserver目录,其中还有一个raft.go的模块与etcdraft库进行通信。etcdserver中与......
  • vue+leaflet示例:克里金插值渲染显示(附源码下载)
    demo源码运行环境以及配置运行环境:依赖Node安装环境,demo本地Node版本:14.19.1。运行工具:vscode或者其他工具。配置方式:下载demo源码,vscode打开,然后顺序执行以下命令:(1)下载demo环境依赖包命令:npmi(2)启动demo命令:npmrundev(3)打包demo命令:npmrunbuild:release示例效果......
  • 直播网站源码,Android中点击图片放大的简单方法
    直播网站源码,Android中点击图片放大的简单方法简单的思路就是把要放大的图片显示在一个对话框中显示出来 Java代码: publicvoidonThumbnailClick(Viewv){//finalAlertDialogdialog=newAlertDialog.Builder(this).create();//ImageViewimgView=getView();//di......
  • ChatGPT 微信接入 C#完整源码
    1.无需搭建服务器,操作极其简单。  2.winform运行程序扫码进行微信登录,勾上自动回复,就可以充当机器人调用chatGPT可实现自动回复,可以申请小号操作。  3.可以识别会话消息和群聊消息,拉入群聊@机器人可以进行群聊的消息回复,可以得到@自己的回复消息。4.代码是完整的也......
  • 一部山寨机配合开源软件即可追踪全球手机位置
    条子告诉我们要通过手机追踪一个人的位置是件很简单的事情,明尼苏达大学的研究表明,对来说,这更简单:一部便宜的手机和开源软件,就可以不需要知道用户的GSM网络也能追踪到其手机的位置。根据该大学科学与工程学员的计算机专家的最新研究,第三方可以轻易地追踪到一个手机用户的位置,因......
  • C#上位机开发源码 上位机项目源代码 采用基于RS485通讯总线的ModbusRtu协议
    C#上位机开发源码上位机项目源代码采用基于RS485通讯总线的ModbusRtu协议,支持用户权限管理、sqlite数据库、实时曲线、历史曲线、历史报表、导出Excel、主界面布局可调带记忆等功能YID:81150611746679046......