左倾红黑树的 F# 代码优化

2024-01-19

我一直致力于将 LLRBT 的 C# 实现移植到 F#,现在它可以正确运行。我的问题是我将如何优化它?

我的一些想法

  • 使用 Node 的可区分联合来删除 null 的使用
  • Remove getters and setters
    • 你不能同时拥有 null 属性和结构

完整源码可以找到here http://github.com/gradbot/f-sharp-llrbt。 C# 代码取自延迟的博客 http://blogs.msdn.com/delay/archive/2009/06/02/maintaining-balance-a-versatile-red-black-tree-implementation-for-net-via-silverlight-wpf-charting.aspx.

目前表现
F# 已用时间 = 00:00:01.1379927 高度:26,计数:487837
C# 已用时间 = 00:00:00.7975849 高度:26,计数:487837

module Erik

let Black = true
let Red = false

[<AllowNullLiteralAttribute>]
type Node(_key, _value, _left:Node, _right:Node, _color:bool) =
    let mutable key = _key
    let mutable value = _value
    let mutable left = _left
    let mutable right = _right
    let mutable color = _color
    let mutable siblings = 0

    member this.Key with get() = key and set(x) = key <- x
    member this.Value with get() = value and set(x) = value <- x
    member this.Left with get() = left and set(x) = left <- x
    member this.Right with get() = right and set(x) = right <- x
    member this.Color with get() = color and set(x) = color <- x
    member this.Siblings with get() = siblings and set(x) = siblings <- x

    static member inline IsRed(node : Node) =
        if node = null then
            // "Virtual" leaf nodes are always black
            false
        else
            node.Color = Red

    static member inline Flip(node : Node) =
        node.Color <- not node.Color
        node.Right.Color <- not node.Right.Color
        node.Left.Color <- not node.Left.Color

    static member inline RotateLeft(node : Node) =
        let x = node.Right
        node.Right <- x.Left
        x.Left <- node
        x.Color <- node.Color
        node.Color <- Red
        x

    static member inline RotateRight(node : Node) =
        let x = node.Left
        node.Left <- x.Right
        x.Right <- node
        x.Color <- node.Color
        node.Color <- Red
        x

    static member inline MoveRedLeft(_node : Node) =
        let mutable node = _node
        Node.Flip(node)

        if Node.IsRed(node.Right.Left) then
            node.Right <- Node.RotateRight(node.Right)
            node <- Node.RotateLeft(node)
            Node.Flip(node)

            if Node.IsRed(node.Right.Right) then
                node.Right <- Node.RotateLeft(node.Right)
        node

    static member inline MoveRedRight(_node : Node) =
        let mutable node = _node
        Node.Flip(node)

        if Node.IsRed(node.Left.Left) then
            node <- Node.RotateRight(node)
            Node.Flip(node)
        node

    static member DeleteMinimum(_node : Node) =
        let mutable node = _node

        if node.Left = null then
            null
        else
            if not(Node.IsRed(node.Left)) && not(Node.IsRed(node.Left.Left)) then
                node <- Node.MoveRedLeft(node)

            node.Left <- Node.DeleteMinimum(node)
            Node.FixUp(node)

    static member FixUp(_node : Node) =
        let mutable node = _node

        if Node.IsRed(node.Right) then
            node <- Node.RotateLeft(node)

        if Node.IsRed(node.Left) && Node.IsRed(node.Left.Left) then
            node <- Node.RotateRight(node)

        if Node.IsRed(node.Left) && Node.IsRed(node.Right) then
            Node.Flip(node)

        if node.Left <> null && Node.IsRed(node.Left.Right) && not(Node.IsRed(node.Left.Left)) then
            node.Left <- Node.RotateLeft(node.Left)
            if Node.IsRed(node.Left) then
                node <- Node.RotateRight(node)
        node

type LeftLeaningRedBlackTree(?isMultiDictionary) =
    let mutable root = null
    let mutable count = 0        

    member this.IsMultiDictionary =
       Option.isSome isMultiDictionary

    member this.KeyAndValueComparison(leftKey, leftValue, rightKey, rightValue) =
        let comparison = leftKey - rightKey
        if comparison = 0 && this.IsMultiDictionary then
            leftValue - rightValue
        else
            comparison

    member this.Add(key, value) =
        root <- this.add(root, key, value)

    member private this.add(_node : Node, key, value) =
        let mutable node = _node

        if node = null then
            count <- count + 1
            new Node(key, value, null, null, Red)
        else
            if Node.IsRed(node.Left) && Node.IsRed(node.Right) then
                Node.Flip(node)

            let comparison = this.KeyAndValueComparison(key, value, node.Key, node.Value)

            if comparison < 0 then
                node.Left <- this.add(node.Left, key, value)
            elif comparison > 0 then
                node.Right <- this.add(node.Right, key, value)
            else
                if this.IsMultiDictionary then
                    node.Siblings <- node.Siblings + 1
                    count <- count + 1
                else
                   node.Value <- value

            if Node.IsRed(node.Right) then
                node <- Node.RotateLeft(node)

            if Node.IsRed(node.Left) && Node.IsRed(node.Left.Left) then
                node <- Node.RotateRight(node)

            node

我很惊讶有如此大的性能差异,因为这看起来像是一个简单的音译。我认为两者都是在“发布”模式下编译的?您是否单独运行这两个版本(冷启动),或者如果两个版本都在同一程序中,则颠倒两者的顺序(例如热缓存)?做过任何分析(有一个好的分析器)吗?比较内存消耗(甚至 fsi.exe 可以帮助解决)?

(我没有看到这种可变数据结构实现有任何明显的改进。)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

左倾红黑树的 F# 代码优化 的相关文章

  • 网页优化:为什么组合文件速度更快?

    我读过 将所有 css 文件合并为一个大文件 或将所有脚本文件合并为一个脚本文件 可以减少 HTTP 请求的数量 从而加快下载速度 但我不明白这一点 我认为如果你有多个文件 最多有一个限制 我相信在现代浏览器上是 10 个 浏览器会并行下载
  • 比较两棵树的伪代码

    这是我遇到过几次的问题 并且不确信我使用了最有效的逻辑 例如 假设我有两棵树 一棵是文件夹结构 另一棵是该文件夹结构的内存 模型 我希望比较两棵树 并生成一棵树中存在的节点列表 而不是另一棵树中存在的节点列表 反之亦然 是否有公认的算法来处
  • WCF - 在服务中抛出故障异常的开销

    我发布了一个question https stackoverflow com questions 81306 wcf faults exceptions versus messages关于使用消息与故障异常在服务之间传达业务规则 我的印象是
  • SQL 执行计划是基于架构还是数据,或者两者兼而有之?

    我希望这个问题不太明显 我已经找到了很多关于解释执行计划的好信息 但有一个问题我还没有找到答案 该计划 更具体地说是相对 CPU 成本 仅基于架构 还是数据库中当前的实际数据 我尝试对我的产品数据库中需要索引的位置进行一些分析 但正在使用我
  • F# 匹配 ->

    我想做类似的东西 Nemerle 语法 def something match STT 1 with st Summ 2 with st AVG gt st summbycol counter STT 在 F 上 那么 F 是真的吗 没有对
  • Python(和 Java)中最快的数据打包

    Sometimes http www codinghorror com blog 2009 01 the sad tragedy of micro optimization theater html our host is wrong na
  • 从函数返回随机值是副作用吗?

    我当时正在编写一些 F 代码 并且正在编写一个从一组字符串中返回随机字符串的函数 假设我有这样的事情 open System let a a b c d let rstring arr string let r new Random arr
  • 如何从 f# 返回一个空元组到 c#? [复制]

    这个问题在这里已经有答案了 我有这个类型正确的 C 函数 static System Tuple
  • 公共领域还好吗?

    在你像我最初那样做出直觉反应之前 请阅读整个问题 我知道它们让你感觉很脏 我知道我们以前都被烧伤过 我知道这不是 好风格 但是公共场所可以吗 我正在开发一个相当大规模的工程应用程序 该应用程序创建并使用结构的内存模型 从高层建筑到桥梁再到棚
  • 字符串文字会被编译器优化吗?

    C 编译器或 NET CLR 是否对字符串文字 常量进行了任何巧妙的内存优化 我可以发誓我听说过 字符串内化 的概念 因此在程序中的任何两位代码中 文字 这是一个字符串 实际上会指代同一个对象 大概是安全的 对于字符串来说是这样的 不可变
  • 强制初始化模板类的静态数据成员

    关于模板类的静态数据成员未初始化存在一些问题 不幸的是 这些都没有能够帮助我解决我的具体问题的答案 我有一个模板类 它有一个静态数据成员 必须为特定类型显式实例化 即必须专门化 如果不是这种情况 使用不同的模板函数应该会导致链接器错误 这是
  • 如何使用 WebSharper 在服务器上生成 Google Visualizations 数据

    我的目标是能够在服务器上为 Google Visualizations 生成数据 然后将其作为 java 脚本传递给客户端 以便可以将其呈现为折线图 我下面的示例可以正确编译 但在浏览器中呈现时会产生错误 在服务器上构建 DataCommo
  • 是否可以在 Java 中创建对象树?

    我正在尝试用 Java 创建对象树 我还想使用一个 Java 类 可以轻松地在树中添加或删除节点 用于此目的的最佳类是什么 示例 这是一个对象数组 数组顶部的对象是字符串 world 这里的叶子是整数 我想添加字符串 This is at
  • 在c#中遍历对象树

    我有一棵由多个对象组成的树 其中每个对象都有一个名称 string id int 以及可能是同一类型的子数组 如何遍历整个树并打印出所有 id 和名称 我是编程新手 坦率地说 我很难理解这个问题 因为我不知道有多少个级别 现在我正在使用fo
  • 将 javascript 合并到一个文件中

    最近阅读了雅虎的网络优化技巧并使用 YSlow 我在我的一个网站上实现了他们的一些想法http www gwynfryncottages com http www gwynfryncottages com你可以在这里看到该文件http ww
  • 跨多个控件共享事件处理程序

    在我用 C 编写的 Windows 窗体应用程序中 我有一堆按钮 当用户的鼠标悬停在按钮上时 我希望按钮的边框发生变化 目前我有以下多个实例 每个按钮一个副本 private void btnStopServer MouseEnter ob
  • 如何在.NET Core上直接调用F#编译器?

    UPD 我想直接从 NET Core SDK 调用 F 编译器 即 fsc 我了解 dotnet build co 但当我只需要编译一个简单的问题时 即 fsc file fs 就足够的情况下 我不想涉及它们 我尝试在 NET Core S
  • R 中 optim() 的优化(L-BFGS-B 需要“fn”的有限值)

    我在 R 中使用 optim 来求解涉及积分的可能性时遇到一些问题 我收到一条错误消息 optim par c 0 1 0 1 LLL method L BFGS B lower c 0 L BFGS B 需要 fn 的有限值 中的错误 下
  • 优化构建中通用函数的 Core Data Swift 转换失败

    我们有一个具有相当广泛的核心数据模型的应用程序 其中有许多用 Objective C 实现的自定义子类 但越来越多的用 Swift 编写的应用程序也使用这些子类 值得一提的是 我们使用 Xcode 7 3 1 针对 iOS 9 3 进行构建
  • VBA 代码基准测试

    对 VBA 代码进行基准测试最准确的方法是什么 在我的例子中 我正在 Excel 中测试代码 除了下面的 2 种之外 还有其他对代码进行基准测试的技术吗 如果有 该方法的优点 缺点是什么 这里有两种流行的方法 First Timer Sub

随机推荐