- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
最近在看《纯函数式数据结构》这本书当我来到 Leftist_tree 的“练习 3.2 直接定义插入而不是通过调用合并”时。我实现了我的版本插入。
let rec insert x t =
try
match t with
| E -> T (1, x, E, E)
| T (_, y, left, right ) ->
match (Elem.compare x y) with
| n when n < 0 -> makeT x left (insert y right)
| 0 -> raise Same_elem
| _ -> makeT y left (insert x right)
with
Same_elem -> t
为了验证它是否有效,我测试了它和书中提供的合并功能。
let rec merge m n = match (m, n) with
| (h, E) -> h
| (E, h) -> h
| (T (_, x, a1, b1) as h1, (T (_, y, a2, b2) as h2)) ->
if (Elem.compare x y) < 0
then makeT x a1 (merge b1 h2)
else makeT y a2 (merge b2 h1)
然后我发现了一个有趣的事情。我使用列表 ["a";"b";"d";"g";"z";"e";"c"]
作为输入来创建这棵树。而且两者的结果是不同的。对于合并方法,我得到了这样一棵树:
我实现的插入方法给我一棵这样的树:
我认为这两种方法之间存在一些细节,即使我遵循“合并”的实现来设计“插入”版本。但后来我尝试了一个逆列表 ["c";"e";"z";"g";"d";"b";"a"],它给了我两个 leftist-tree-by-insert树。这真的让我很困惑,我不知道我的插入方法是错误的还是正确的。所以现在我有两个问题:
全部代码
module type Comparable = sig
type t
val compare : t -> t -> int
end
module LeftistHeap(Elem:Comparable) = struct
exception Empty
exception Same_elem
type heap = E | T of int * Elem.t * heap * heap
let rank = function
| E -> 0
| T (r ,_ ,_ ,_ ) -> r
let makeT x a b =
if rank a >= rank b
then T(rank b + 1, x, a, b)
else T(rank a + 1, x, b, a)
let rec merge m n = match (m, n) with
| (h, E) -> h
| (E, h) -> h
| (T (_, x, a1, b1) as h1, (T (_, y, a2, b2) as h2)) ->
if (Elem.compare x y) < 0
then makeT x a1 (merge b1 h2)
else makeT y a2 (merge b2 h1)
let insert_merge x h = merge (T (1, x, E, E)) h
let rec insert x t =
try
match t with
| E -> T (1, x, E, E)
| T (_, y, left, right ) ->
match (Elem.compare x y) with
| n when n < 0 -> makeT x left (insert y right)
| 0 -> raise Same_elem
| _ -> makeT y left (insert x right)
with
Same_elem -> t
let rec creat_l_heap f = function
| [] -> E
| h::t -> (f h (creat_l_heap f t))
let create_merge l = creat_l_heap insert_merge l
let create_insert l = creat_l_heap insert l
end;;
module IntLeftTree = LeftistHeap(String);;
open IntLeftTree;;
let l = ["a";"b";"d";"g";"z";"e";"c"];;
let lh = create_merge `enter code here`l;;
let li = create_insert l;;
let h = ["c";"e";"z";"g";"d";"b";"a"];;
let hh = create_merge h;;
let hi = create_insert h;;
<强>16。 2015 年 10 月更新
通过更精确地观察这两个实现,很容易发现不同之处在于合并一个基础树T (1, x, E, E)
或插入一个元素x
我用的是图表,表达的更清楚。
所以我发现我的插入版本总是会使用更多的复杂性来完成他的工作并且没有利用左树的优势或者它总是在更糟糕的情况下工作,即使这个树结构完全是“左”的。
如果我改变一点点,两段代码会得到相同的结果。
let rec insert x t =
try
match t with
| E -> T (1, x, E, E)
| T (_, y, left, right ) ->
match (Elem.compare x y) with
| n when n < 0 -> makeT x E t
| 0 -> raise Same_elem
| _ -> makeT y left (insert x right)
with
Same_elem -> t
所以对于我的第一个问题:我认为答案并不准确。它可以真正构建左派树,但总是在糟糕的情况下工作。
第二个问题有点无意义(我不确定)。但对于这种情况仍然很有趣。例如,尽管合并版本的工作效率更高,但是从列表构建树而不需要像我提到的那样插入顺序 (["a";"b";"d";"g";"z"; "e";"c"], ["c";"e";"z";"g";"d";"b";"a"] ,如果顺序不重要,对我来说我认为它们是同一个集合。)合并功能无法选择更好的解决方案。 (我认为 ["a";"b";"d";"g";"z";"e";"c"] 的树结构优于 ["c";"e";"z";"g";"d";"b";"a"])
所以现在我的问题是:
最佳答案
每个子右脊柱为空的树只是一个列表。因此,一个简单的列表是一个更好的列表结构。运行时属性将与列表相同,这意味着例如插入将花费 O(n)
时间而不是所需的 O(log n)
时间。
对于一棵树,您通常需要一棵平衡树,理想情况下,一个节点的所有子节点大小都相同。在您的代码中,每个节点都有一个 rank
并且目标是每个节点的左侧和右侧具有相同的等级。如果您在树中没有完全 2^n - 1
条目,这是不可能的,您必须允许树中存在一些不平衡。通常允许 1 或 2 的等级差异。插入应该在等级较小的一侧插入元素,移除必须重新平衡任何超过允许等级差异的节点。这使树保持合理平衡,确保保留所需的运行时属性。
检查你的教科书在你的情况下允许的排名差异。
关于data-structures - 左堆二版创建实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33135564/
这是我第一次在结构中使用结构。我在编译我的程序时遇到了这个错误。错误:字段“结果”的类型不完整。 错误是指这行代码。-->结构result_t结果; 有什么帮助吗? :)谢谢。 typedef str
typedef struct mensagem { int sender ; int receiver ; char *text ; } *Item ; typedef str
我正在使用 ExpressionEngine 和 Structure 附加组件的最新版本。 我正在寻找有关生成 4 项导航栏的帮助,其中两项位于不同的结构级别。 我的结构行如下所示: 服务(父) --
我正在处理一个非常大的数据集。本质上,我将处理数百万条记录并将值存储到数据集中。 每次我存储一个值时,我必须首先检查以确保该值不在数据结构中。如果值在数据结构中,我必须更新(或删除/添加)记录以更新计
我正在尝试分别使用视频帧和音频来分析视频,我想出了一个看起来像这样的模型 现在,我将训练数据分成两个生成器 - 一个用于视频,一个用于音频。我必须进一步将生成器分成两半,我认为这是我遇到错误的地方。因
我有一个创建 N 个进程的程序,每个进程创建 M 个线程。 我还有一个结构需要传递给线程函数。 当我像这样创建 M 个线程时: thread_args_t** thread_arg = malloc(
我正在试图弄清楚如何实现一个等待事件发出信号的函数。指针由DLL函数返回,该函数是存储3个项的结构。其中两个是句柄,它们只是指针,最后是一些随机的未使用的指针。我真的不确定这应该如何格式化,因为我两个
根据PLCOpen、IEC-61131标准,是否可以在声明中初始化结构体? 我正在考虑类似于 this C++ question 的事情. 最佳答案 您可以在结构声明时向结构变量添加默认值。您还可以在
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
在纯 C 中工作,将结构嵌套在其他结构或指向结构的指针中更好。使用指针可以更容易地实现良好的对齐,但是访问内部结构需要额外的取消引用。只是具体地说: typedef struct {
我正在使用 Qt Creator 开发应用程序。 我不是一个好的C++程序员,所以可能会有概念上的错误等。 我在复制结构数组并返回结构时遇到问题。 有很多与类似标题相关的解决方案,但无法解决我的问题。
我正在尝试使用带水印的 dropDuplicate 函数对流数据进行重复数据删除。我目前面临的问题是我必须为给定记录设置两个时间戳 一个是事件时间戳 - 从源创建记录的时间戳。 另一个是传输时间戳 -
很难说出这里问的是什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或言辞激烈,无法以目前的形式合理回答。如需帮助澄清此问题以便可以重新打开,visit the help center . 10年前关
我尝试构建一个嵌套循环,用于创建 2 维零矩阵来解决 LCS 问题(动态规划)。这后来用于计算 Rouge-L 分数(输入是张量,而不是字符串),但它总是出错引发 ValueError: The tw
我曾多次使用 HDFS 和 Kafka,我注意到 Kafka 比 HDFS 更可靠。因此,现在使用 Spark-structured-streaming 时,我很惊讶检查点仅适用于 HDFS。使用 K
C11,6.7.2.1 结构和 union 说明符,约束,3(添加了强调): A structure or union shall not contain a member with incomple
在 emacs lisp 中,各种树结构是常见的。 custom.el通过:type提供论据 defcustom定义自定义变量的预期形状的标准方法。但是有没有一种标准的方法来验证一些随机 emacs
我在网上遇到了以下面试问题。 描述一个数据结构,其中 getValue(int index)、setValue(int index, int value) 和 setAllValues(int val
我正在使用 sqldf 对一个巨大的文件进行子集化。以下命令为我提供了一个 100 行和 42 列的 data.frame。 first <- read.csv.sql("first.txt", se
来自这里的 C++ 背景。我需要为我的一门类(class)编写 C 语言,但我从未接触过这一类(class)。这两个声明之间有什么区别?为什么要包含 struct 关键字?有不同的含义吗?它们在 C+
我是一名优秀的程序员,十分优秀!