微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在惯用的C ++中实现X-fast / Y-fast trie

如何解决在惯用的C ++中实现X-fast / Y-fast trie

我正在用惯用的C ++实现X-fast / Y-fast trie数据结构,一半用于娱乐,一半用于学习。我想在选择合适的子数据结构进行实施时获得帮助。

X-Fast trie(https://en.wikipedia.org/wiki/X-fast_trie)具有以下要求:

enter image description here

  • 具有k位的整数存储在按位线程化的二进制trie中。例如,如果键为13 = 1101,则我们存储1、11、110、1101。1101是叶。
  • 对于每个级别,都有一个哈希表,其中包含该级别中的所有节点。
  • 叶子在双链表中以递增顺序连接。
  • 如果内部节点有一个丢失的子代,则每个缺失的0均指向其有序前任,而每个缺失的1指向其有序后继。

我想到的第一件事是:

struct Node {
    std::optional<std::size_t> value;
    std::weak_ptr<Node> parent;
    std::shared_ptr<Node> left;
    std::shared_ptr<Node> right;
};

我之所以选择std::optional<std::size_t>是因为根不应该包含值。对于Node*,我更喜欢parent;对于std::unique_ptr<Node>,我更喜欢left/right,但是我不得不更改它,因为叶节点的所有权在多个祖先之间共享。

对于级别搜索结构:

std::array<std::unordered_map<std::size_t,std::weak_ptr<Node>>,k>

其中k是类型为std::size_t的模板参数。

对于最底层叶子的链表:

std::list<std::weak_ptr<Node>>

在这里讨厌

  • std::optional。有没有更好的选择来确保在不使用std::optional的情况下根不包含值?我不想为只照顾一个节点而疯狂地增加不必要的开销。
  • 底层链接列表的选择。对于给定的叶子,我必须访问其上一个/下一个叶子。当然,我可以通过添加std::weak_ptr<Node> prevstd::weak_ptr<Node> next作为Node的成员变量来实现。但是同样,我不想只为底层打理而不必要的开销。我想使用std::list<std:weak_ptr<Node>>::iterator,但是如何从通过根路径访问的叶指针std::weak_ptr<Node>中获得这些迭代器?

我认为的解决方法

  • NodeBase用作抽象基类,并制作派生类NodeRootNodeInternalNodeLeaf。 像这样:
    class NodeBase {
    };

    class NodeNonRoot;

    class NodeRoot : public NodeBase {
        std::shared_ptr<NodeNonRoot> left;
        std::shared_ptr<NodeNonRoot> right;
    };

    class NodeNonRoot : public NodeBase {
        std::weak_ptr<NodeBase> parent;
        std::size_t data;
    };

    class NodeInternal : public NodeNonRoot {
        std::shared_ptr<NodeNonRoot> left;
        std::shared_ptr<NodeNonRoot> right;
    };

    class NodeLeaf : public NodeNonRoot {
        std::weak_ptr<NodeLeaf> prev;
        std::weak_ptr<NodeLeaf> next;
    };

缺点:类层次结构的复杂性。

  • ...别无选择

解决方法

停止尝试为此使用智能指针,以简化操作:

struct Node {
    std::size_t value = 0;
    Node* left = nullptr;
    Node* right = nullptr;
};

这似乎足够了。您现在可以使用相同的leftright指针来构建叶子的双向链接列表,至于没有值的根,谁在乎,只是不要使用{{1 }}元素。无论如何,您都需要跟踪树的级别。

在创建基于节点的容器时不需要智能指针。它们没有用在valuestd::list等中。您可以自己在整个容器中管理元素的生存期,因此不需要节点之间成熟的生存期关系因为您不允许外部代码创建或销毁它们。

,

内部节点不包含值。通常,根节点旁边将有许多内部节点,并且它们都不包含值。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。