Zipper 数据结构是什么?我应该使用它吗?

发布于 2024-07-10 04:48:54 字数 253 浏览 8 评论 0原文

问题很简单:我无法理解 Zipper 数据结构。

我的问题与其在树上的用途有关。

我想了解如何使用拉链更改树节点。 以及如何不复制整个树(或其中的大部分)。

请澄清我的拉链是否有误。 也许它不能帮助更新树?
或者,也许可以更新树,但我只是看不到路?

The question is simple: I cannot understand the Zipper data structure.

My question is related to its uses with a Tree.

I want to understand how can I change the tree node using zipper. And how not to copy the whole tree (or the most part of it).

Please, clarify if I'm wrong with zipper. Maybe it cannot help with the tree update?
Or, maybe, it is possible to update the tree and I just cannot see the way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

套路撩心 2024-07-17 04:48:54

让我们从列表的 Zipper 类比开始。 如果您想修改列表的第 n 个元素,则需要 O(n),因为您必须复制第 n-1 个元素。 相反,您可以将列表保留为结构((前 n-1 个元素反转)第 n 个元素(剩余元素))。 例如,可在 3 处修改的列表 (1 2 3 4 5 6) 将表示为 ((2 1) 3 (4 5 6))。 现在,您可以轻松地将 3 更改为其他内容。 您还可以轻松地将焦点向左移动((1) 2 (3 4 5 6)) 和向右移动((3 2 1) 4 (5 6))

拉链与应用于树木的想法相同。 您代表树中的某个焦点加上一个上下文(向上到父母,向下到孩子),它以一种可以轻松修改焦点并且可以轻松上下移动焦点的形式提供整个树。

Let's start with the Zipper-analog for lists. If you'd like to modify the nth element of a list, it takes O(n) because you have to copy the n-1 first elements. Instead, you can keep the list as a structure ((first n-1 elements reversed) nth element (remaining elements)). For example, the list (1 2 3 4 5 6) modifiable at 3 would be represented as ((2 1) 3 (4 5 6)). Now, you can easily change the 3 to something else. You can also easily move the focus left ((1) 2 (3 4 5 6)) and right ((3 2 1) 4 (5 6)).

A zipper is the same idea applied to trees. You represent a certain focus in the tree plus a context (up to parents, down to children) which gives you the whole tree in a form where it's easily modifiable at the focus and it's easy to move the focus up and down.

怪我入戏太深 2024-07-17 04:48:54

这是一篇非常好的文章,解释了 在 Haskell 中使用拉链作为平铺窗口管理器。 维基百科的文章不是一个很好的参考。

简而言之,拉链是指向树或列表结构中特定节点的指针或句柄。 拉链提供了一种自然的方式来获取树结构并将其视为树被焦点节点“拾取” - 实际上,您可以获得第二棵树,而不需要原始树的额外副本或影响其他用户那个树。

给出的示例显示了如何让窗口最初按屏幕上的位置排序,然后使用指向焦点窗口的拉链来模拟焦点。 您可以获得一组很好的 O(1) 操作,例如插入和删除,而无需对焦点窗口进行特殊处理或编写额外的代码。

Here is a very nice article explaining using the zipper for a tiling window manager in Haskell. The Wikipedia article is not a good reference.

In short, the zipper is a pointer or handle to a particular node in a tree or list structure. The zipper gives a natural way of taking a tree structure and treating it as though the tree was "picked up" by the focused node - in effect, you get a second tree without requiring additional copies made of the original tree or affecting other users of the tree.

The example given shows how you have the windows originally sorted by location on the screen, and then to model focus you use a zipper pointed at the focus window. You get a nice set of O(1) operations such as insert and delete without having to special case the focus window or write additional code.

去了角落 2024-07-17 04:48:54

Learn You a Haskell 还有关于拉链的精彩章节

Learn You a Haskell also has a great chapter about zippers.

内心激荡 2024-07-17 04:48:54

该代码重点关注如图所示的单元格。 有上方、下方、左侧和右侧区域。 我们在这个网格上移动。 焦点是绿色方块。

输入图片此处描述

基本哈斯克尔

type cell = { alive : bool ; column : int ; row : int }
;;

type grid = {gamegrid : cell list list}
;;

type gridzipper  =
             { above : grid
             ; below : grid
             ; left  : cell list
             ; right : cell list
             ; focus : cell }

let left g =
match g.left with
 [] -> None 
| hd::tl ->  let newgridzipper = { g  with focus = hd; left = tl; right = g.right @ [g.focus] } in
             Some(newgridzipper)
;;

left 函数将焦点移至左侧。 类似地,其他功能将焦点转移到其他网格单元。

输入图片此处描述

The code focuses on a cell like this picture shows. There are areas above,below, to the left and to the right. We move over this grid. The focus is the green square.

enter image description here

Basic Haskell

type cell = { alive : bool ; column : int ; row : int }
;;

type grid = {gamegrid : cell list list}
;;

type gridzipper  =
             { above : grid
             ; below : grid
             ; left  : cell list
             ; right : cell list
             ; focus : cell }

let left g =
match g.left with
 [] -> None 
| hd::tl ->  let newgridzipper = { g  with focus = hd; left = tl; right = g.right @ [g.focus] } in
             Some(newgridzipper)
;;

The left function moves the focus to the left. Similarly the other functions shift the focus to other grid cells.

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文