左链表与右链表,替换速度
在 Mathematica 中构造链表有两种明显的方法,“左”:
{1, {2, {3, {4, {5, {6, {7, {}}}}}}}}
和“右”:
{{{{{{{{}, 7}, 6}, 5}, 4}, 3}, 2}, 1}
这些可以通过以下方式实现:
toLeftLL = Fold[{#2, #} &, {}, Reverse@#] & ;
toRightLL = Fold[List, {}, Reverse@#] & ;
如果我使用这些,并执行一个简单的 ReplaceRepeated
来遍历链接列表中,我得到了截然不同的 Timing
结果:
r = Range[15000];
left = toLeftLL@r;
right = toRightLL@r;
Timing[i = 0; left //. {head_, tail_} :> (i++; tail); i]
Timing[i = 0; right //. {tail_, head_} :> (i++; tail); i]
(* Out[6]= {0.016, 15000} *)
(* Out[7]= {5.437, 15000} *)
为什么?
There are two obvious ways to structure a linked list in Mathematica, "left":
{1, {2, {3, {4, {5, {6, {7, {}}}}}}}}
And "right":
{{{{{{{{}, 7}, 6}, 5}, 4}, 3}, 2}, 1}
These can be made with:
toLeftLL = Fold[{#2, #} &, {}, Reverse@#] & ;
toRightLL = Fold[List, {}, Reverse@#] & ;
If I use these, and do a simple ReplaceRepeated
to walk through the linked list, I get drastically different Timing
results:
r = Range[15000];
left = toLeftLL@r;
right = toRightLL@r;
Timing[i = 0; left //. {head_, tail_} :> (i++; tail); i]
Timing[i = 0; right //. {tail_, head_} :> (i++; tail); i]
(* Out[6]= {0.016, 15000} *)
(* Out[7]= {5.437, 15000} *)
Why?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
ReplaceRepeated
使用SameQ
来确定何时停止应用规则。当
SameQ
比较两个列表时,它会检查长度,如果相同,则将SameQ
应用于从第一个到最后一个的元素。在left
的情况下,第一个元素是整数,因此很容易检测不同的列表,而对于right
列表,第一个元素是深度嵌套的表达式,因此它需要遍历它。这就是缓慢的原因。现在将其与:
EDIT In response to Mr.Wizard's question of options to speed this up. One should write a custom same testings.
ReplaceRepeated
does not provide such an option, so we should useFixedPoint
andReplaceAll
:EDIT2: Faster yet:
ReplaceRepeated
usesSameQ
to determine when to stop applying the rule.When
SameQ
compares two lists, it checks lengths, and if the same, then appliesSameQ
to elements from the first to the last. In the case ofleft
the first element is an integer, so it is easy to detect distinct lists, while forright
list the first element is the deeply nested expression, so it needs to traverse it. This is the reason for the slowness.Now compare this with:
EDIT In response to Mr.Wizard's question of options to speed this up. One should write a custom same testings.
ReplaceRepeated
does not provide such an option, so we should useFixedPoint
andReplaceAll
:EDIT2: Faster yet: