如何为单列和双列节点c ++构造模板层次结构

Posted

技术标签:

【中文标题】如何为单列和双列节点c ++构造模板层次结构【英文标题】:How to construct template hierarchy for singly and doubly list nodes c++ 【发布时间】:2021-01-16 02:45:12 【问题描述】:

我只想实现两种类型的节点(只有节点): 单链表的节点和双向链表的节点类。 显而易见的解决方案是定义两个单独的类:

template <typename T>
struct SinglyNode

    using node_pointer = SinglyNode<T>*;
    SinglyNode(T data = T, node_pointer next = nullptr)
        : m_data data ,
        m_next next 
    
    T m_data;
    node_pointer m_next;
;

template <typename T>
struct DoublyNode

    using node_pointer = DoublyNode<T>*;
    DoublyNode(T data = T, node_pointer prev = nullptr, node_pointer next = nullptr)
        : m_data data ,
        m_prev  prev ,
        m_next next 
    
    T m_data;
    node_pointer m_prev;
    node_pointer m_next;
;

我知道 DoublyNode 和 SinglyNode 都有数据,并链接到下一个节点(节点不是同一类型,SinglyNode::m_next 是 SinglyNode* 类型,而 DoublyNode::m_next 是 DoublyNode* 类型), 此外,DoublyNode 还具有指向前一个节点的链接。

但是我怎样才能创建一个层次结构来擦除/最小化代码重复,以便用户可以使用派生类成员而无需动态转换到派生节点?

注意:对我来说,一个代码 sn-p 或一些提示就足够了。

【问题讨论】:

"节点不属于同一类型" 您需要澄清这一点。您发布的模板具有相同类型的节点,例如node_pointer = SinglyNode&lt;T&gt;*; @dxiv 已编辑!! 你可以推导出struct DoublyNode : public SinglyNode&lt;T&gt;,例如here。或者在刚刚发布的答案中使用 CRTP 更优雅地进行操作。如果这就是您所说的“使用派生类成员而不需要 dynamic_cast”,那么您可以在问题中更清楚地说明。 【参考方案1】:

使用 CRTP,您可以执行以下操作:

template <typename Derived, typename T>
struct SinglyNodeCRTP

    using node_pointer = Derived*;
    SinglyNodeCRTP(T data = T, node_pointer next = nullptr)
        : m_data data ,
        m_next next 
    
    T m_data;
    node_pointer m_next;
;


template <typename T>
struct SinglyNode : SinglyNodeCRTP<SinglyNode<T>, T>

    using SinglyNodeCRTP::SinglyNodeCRTP;
;

template <typename T>
struct DoublyNode : SinglyNodeCRTP<DoublyNode<T>, T>

    using node_pointer = typename SinglyNodeCRTP<DoublyNode<T>, T>::node_pointer;
    DoublyNode(T data = T, node_pointer prev = nullptr, node_pointer next = nullptr)
        : SinglyNodeCRTP<DoublyNode<T>, T> data , prev ,
        m_prev prev 
    
    node_pointer m_prev;
;

【讨论】:

为什么我们需要这个using SinglyNodeCRTP::SinglyNodeCRTP; Inherit constructors。或者,您可以像 DoublyNode 那样做。 谢谢,我不知道 CRTP 和“构造函数继承”。【参考方案2】:

得到我的问题答案后的最终代码。

      template <typename N, typename T>
      struct node_base 
        T m_value;
        N* m_next;
        node_base(T value = T, N* next = T)
            : m_value value ,
            m_next next 
        
      ;

      template <typename T>
      struct snode : public node_base<snode<T>, T>
      
          using node_base::node_base;
      ;

      template <typename T>
      struct dnode : public node_base<dnode<T>, T>
      
        using node_type = dnode<T>;
        dnode(T value = T, node_type* prev = nullptr, node_type* next = nullptr)
            : node_base<node_type, T> value, next ,
            m_prevprev
        
        dnode<T>* m_prev;
      ;

【讨论】:

以上是关于如何为单列和双列节点c ++构造模板层次结构的主要内容,如果未能解决你的问题,请参考以下文章

数据结构(C语言版)严蔚敏->二叉树(链式存储结构)的构造及其几种遍历方式(先序中序后序层次)和线索二叉树

数据结构(C语言版)严蔚敏->二叉树(链式存储结构)的构造及其几种遍历方式(先序中序后序层次)和线索二叉树

数据结构(C语言版)严蔚敏->二叉树(链式存储结构)的构造及其几种遍历方式(先序中序后序层次)和线索二叉树

数据结构(C语言版)严蔚敏->二叉树(链式存储结构)的构造及其几种遍历方式(先序中序后序层次)和线索二叉树

可克隆层次结构中的C ++副本构造函数和赋值

10,组合模式(Composite Pattern)是将对象组合成树形结构以表示“部分--整体”的层次结构。使得用户对单个对象和组合对象的使用具有一致性。