3

我有一个tree_node班级和一个tree班级。

template<typename T>
class tree_node
{
public:
   tree_node(const std::string& key_, const T& value_) 
        : key(key_), value(value_)
   {
   }
private:
   T value;
   std::string key;
};

template<typename T>
class tree
{
public:
   tree() : root(new tree_node<T>("", ???)) { }
private:
   tree_node<T>* root;
};

tree_node期望创建时的实例T。我怎样才能通过它????我可以说T(),但它只有在T有一个无参数的构造函数时才会起作用。我不能有无参数构造函数,因为如果没有无参数构造函数tree_node,它将无法编译。T

我正在寻找一种tree_node可以正确保存所有类型(包括指针类型)的设计方法。

编辑

在尝试了各种方法后,我发现这boost::optional在这种情况下很有帮助。我可以T value进入boost::optional<T> value。这将解决空构造函数问题。所以我可以有另一个构造函数重载,tree_node它只需要一个key. 这可以由根节点使用。这是正确的方法吗?

谢谢..

4

4 回答 4

4

初始根值应为零。如果你推送新节点,你显然知道价值。

template<typename T> 
class tree 
{ 
public: 
   tree() : root(0) { } 
   void push (const std::string& key, const T & t) {
      if (root == 0) {
        root = new tree_node<T>(key, t);
      } else {
         // Make complex tree
      }
   }
private: 
   tree_node<T>* root; 
}; 

添加

如果您使用后缀树,您应该制作两种类型的顶点:

enum NodeType { EMPTY_NODE, VALUE_NODE };

class base_tree_node 
{ 
public: 
   base_tree_node() :parent(0), left(0), right(0) {}

   virtual NodeType gettype() = 0;

protected: 
   base_tree_node* parent;
   base_tree_node* left;
   base_tree_node* right;
}; 

class empty_tree_node : base_tree_node
{
   virtual NodeType gettype()  { return EMPTY_NODE; }
}

template<typename T> 
class tree_node : base_tree_node 
{ 
public: 
   tree_node(const std::string& key_, const T& value_)  
        : key(key_), value(value_) 
   { 
   } 

   virtual NodeType gettype()  { return VALUE_NODE; }

private: 
   T value; 
   std::string key; 
}; 
于 2010-02-16T17:23:15.293 回答
3
tree( const T & t ) : root(new tree_node<T>("", t )) { }
于 2010-02-16T17:24:20.077 回答
0

我曾经做过一个链表(只是为了好玩),它需要一个不打算保存任何数据的哨兵节点,我有以下结构:

struct BaseNode
{
    BaseNode* next;
    BaseNode(BaseNode* next): next(next) {}
};

template <class T>
struct Node: public BaseNode
{
    T data;
    Node(const T& data, BaseNode* next): BaseNode(next), data(data) {}
};

template <class T>
struct List
{
    BaseNode* head;
    List(): head(new BaseNode(0)) {}
    void add(const T& value)
    {
        Node<T>* new_node = new Node<T>(value, head->next);
        head->next = new_node;
    }
    T& get_first()
    {
        assert(head->next);
        return static_cast<Node<T>*>(head->next)->data;
    }
    //...
};

类本身必须确保它获得必要的强制转换,并且不会尝试将 head 或 root 自身转换为Node<T>.

于 2010-02-16T17:39:24.307 回答
0

树节点应该有(或者是)子节点的集合。一棵树应该有(或者是)一个根节点的集合。这两个集合应该是相同的类型。很简单:

template <class T>
class NodeCollection
{
    std::vector<Node<T> *> nodes;

public:
    // any operations on collection of nodes
    // copy ctor and destructor a must!
};

template <class T>
class Node : public NodeCollection<T> 
{
    T value;

public:
    // ctor
    // access to value
};

template <class T>
class Tree : public NodeCollection<T> 
{
public:
    // ctor
};

这样,Treeand的共享定义Node实际上在 中NodeCollection,因此Tree不需要携带虚拟值。

于 2010-02-16T18:14:42.017 回答