具有多态性的2-3树的设计与实现

Posted

技术标签:

【中文标题】具有多态性的2-3树的设计与实现【英文标题】:Design and implementation of a 2-3 tree with polymorphism 【发布时间】:2016-01-05 22:11:46 【问题描述】:

我必须使用node 的基类和leafinnernode 的派生类(即两个“are-a”节点)来实现2-3 树。

但我不明白如何在简单的情况下从插入开始。既然我们调用node的方法来插入,那么它应该如何知道我们插入的是innernode还是leaf呢?一个节点应该如何将自己更改为leafinnernode

关于如何解决这个问题的任何提示/想法?

这是结构,但我并没有走多远。

typedef int TreeKey;

class node 
public:
    virtual ~node() 

    virtual void insert(TreeKey k, string d);
    virtual void deletenode(TreeKey k);
    virtual void findnode();
    virtual node * findnode(TreeKey key);

protected:
    struct info 
        TreeKey key;
        string data;
    ;
    node* parent=nullptr;
;

class leaf : node 
    info i;
public:
    virtual void insert(TreeKey k, string d);


;

class innerNode : node 
    vector<info> inf;
    vector<node*> vect;

public:
    virtual void insert(TreeKey k, string d);


;

注意:在这个 2-3 树中,数据只位于叶子中。

【问题讨论】:

【参考方案1】:

一种做事方式如下。还有其他的。

有 4 个独立的类:一个 2-leaf-node、一个 3-leaf-node、一个 2-internal-node 和一个 3-internal-node。此解决方案摆脱了向量,因此最大限度地减少了动态分配。

插入一个元素,而不是一个节点。每个节点都知道如何处理插入的元素。内部节点将元素传递给子节点之一。叶节点吸收元素。

2 节点通过变为 3 节点来吸收元素。一个 3 节点通过成为两个 2 节点来吸收一个元素,并将一个元素传回其父节点以进行吸收。然后父级本身会发生变化并可能向上传递一个元素。这一直持续到某些 2 节点更改为 3 节点(其父节点不需要更改,只需替换其子指针),或者一个元素一直传播回根节点,并创建一个新根节点。

一个节点如何“变成”别的东西?这不可以。相反,它创建它应该成为的新事物,将其信息复制到新事物,将新创建的事物返回给调用者,然后删​​除自己。然后调用者要么用新创建的替换它的旧孩子,要么它自己“变成”别的东西。

节点的insert 方法签名可能如下所示:

 typedef enum none, expand23, split322 action;
 action Node::insert(info& element, Node*& newNode1, Node*& newNode2);

如果该节点是一个 2 节点并且它变成了一个 3 节点,则该方法会创建一个新的 3 节点并将其传递回 newNode1。父级必须在看到expand23 时替换相应的子级指针。父级本身不会扩展或拆分,因此 insert 返回 none

如果节点是一个 3 节点并且它分裂,该方法会创建两个新的 2 节点并将它们传递回 newNode1newNode2。它还传回一个元素供父级吸收。父母会根据类型选择expand23split322

如果根返回split322,则创建一个新根

“在这棵 2-3 树中,数据只存在于叶子中”——刚刚注意到这句话。我不确定这怎么可能奏效。 2-3 树在每个节点中都有 1 或 2 个数据项,而不仅仅是叶子。否则它无法工作。所以我几乎忽略了这句话。

如果您不想为 2 节点和 3 节点设置单独的类,则不需要 expand23,因为 2 节点可以变成 3 节点而无需删除自身。 split322 保持不变。在这种情况下,我不会使用向量。由于叶节点仅存储存在于其他地方的键的副本,因此它们可以存储为指向键的 3 个(智能)指针(不是数组,只是 3 个单独的变量)。您可以通过查看第三个指针来区分 2 节点和 3 节点。如果它是 nullptr,则这是一个 2 节点。叶子中的数据也是如此,将其存储在 3 个单独的指针中。

【讨论】:

关于最后一部分,键可以无处不在,但实际数据应该只在叶子中,(我看到还有另一个版本,但我们应该这样做)。这是一个示例:pages.cs.wisc.edu/~vernon/cs367/notes/10.23TREE.html 如果数据只保存在叶子中,为什么它不起作用? 啊哈,它们在内部节点中存储密钥的副本,在叶子中存储密钥和数据。这确实有效。答案并不取决于节点中究竟存储了什么,算法保持不变。 好的,所以要清除另一件事,您将指向外部基类节点的指针存储在 main 中?并使用它的方法来涓涓细流? 所以一开始'node.insert(element)'会创建一个叶子并检查它可以存储在哪里?如果在从节点转到叶子和内部节点时将其删除,那么如何保留外部指针?

以上是关于具有多态性的2-3树的设计与实现的主要内容,如果未能解决你的问题,请参考以下文章

JAVA 作业 实验名称:接口,继承与多态

多态性与虚函数

47.多态

JavaSE视频学习阶段性总结 六(多态与接口)

20172313 2017-2018-2 《程序设计与数据结构》第八周学习总结

C++程序设计POJ》《WEEK6 多态与虚函数》《多态的实现原理》《虚函数表》