在rooted二进制树模板类中重载operator =()

时间:2013-11-20 17:55:35

标签: c++ algorithm operator-overloading binary-tree graph-traversal

我正在编写一个名为RootedBinaryTree的模板类,它有一个类似于链表的结构,其元素的类型为Node,这是我在下面的头文件中定义的结构。二叉树中的每个节点都有parent Node *,可以有leftChild Node *rightChild Node *或没有子节点。 (例如:如果你要绘制一个带根的二叉树,它应该看起来像这个http://mathworld.wolfram.com/images/eps-gif/CompleteBinaryTree_1000.gif)。

有根二进制树有两个成员:rootcurrentPosition,它们是node类型。 当我重载operator=()时,我必须做currentPosition = RHS.currentPosition;之类的事情(这是我目前所写的)。我知道这是不正确的,我需要做的是在*this树中找到与currentPosition Node *树中的RHS对应的节点。

我的问题是:遍历RHS树以查找其currentPosition Node *并在调用树中找到相应的Node的算法是什么?

我的想法是创建一个空字符串并使用某种深度优先搜索算法遍历RHS,从根目录开始直到我找到currentPosition,并通过附加一个跟踪我到达那里的路径0到字符串的结尾如果我向下走到树的左边,或者如果我向下走到树的右边,然后使用该字符串来遍历*this树,这应该会带我到相应的Node。但是,我知道必须有更好的方法去做(部分来自直觉,部分是因为我的导师告诉我有更好的方法哈哈)。

以下是相关文件:

RootedBinaryTree.h

#ifndef ROOTEDBINARYTREE_H
#define ROOTEDBINARYTREE_H 

template <class T>
class RootedBinaryTree
{
private:
    template <class T>
    struct Node
    {
        T nodeData;
        Node<T> * parent; 
        Node<T> * leftChild; 
        Node<T> * rightChild; 

        Node<T>::Node()
        {
            parent = leftChild = rightChild = 0L; 
        }
    }; 
    Node<T> * root;
    Node<T> * currentPosition; 

    void copySubtree(Node<T> * & target, Node<T> * const & original);
    void deleteSubtree(Node<T> * n); 

public:
    RootedBinaryTree(const T & rootData);
    RootedBinaryTree(const RootedBinaryTree<T> & original);
    ~RootedBinaryTree(); 
    void toRoot();
    bool moveLeft();
    bool moveRight();
    bool moveUp(); 
    T getData() const {return currentPosition->nodeData;}; 
    RootedBinaryTree<T> & operator=(const RootedBinaryTree<T> & RHS);
    void combineTrees(const RootedBinaryTree<T> & leftTree, const RootedBinaryTree<T> & rightTree);
    void setNodeData(const T & nodeData); 
};

#endif

RootedBinaryTree.cpp

#ifndef ROOTEDBINARYTREE_CPP
#define ROOTEDBINARYTREE_CPP

#include "RootedBinaryTree.h"

template<class T>
void RootedBinaryTree<T>::copySubtree(Node<T> * & target, Node<T> * const & original) 
{// Assumes that target's leftChild = rightChild = 0L. I.e. target is a leaf. 
    target = new Node<T>; 
    if(original->leftChild != 0L)
    {
        target->leftChild->parent = target;
        copySubtree(target->leftChild, original->leftChild); 
    } 
    else
    { 
        target->leftChild = 0L; 
    }
    // ^^^ copy targets left (and right) children to originals
    if(original->rightChild != 0L) 
    {
        target->rightChild->parent = target;
        copySubtree(target->rightChild, original->rightChild);
    }
    else
    {
        target->rightChild = 0L; 
    }
    target->nodeData = original->nodeData;
}

template <class T> 
void RootedBinaryTree<T>::deleteSubtree(Node<T> * n)                                                // Done 
{// Assumes that n is a valid node. 
    if(n->leftChild != 0L) deleteSubtree(n->leftChild);                                             // Delete all nodes in left subtree
    if(n->rightChild != 0L) deleteSubtree(n->rightChild);                                           // Delete all nodes in right subtree 
    delete n; 
}

template <class T>
RootedBinaryTree<T>::RootedBinaryTree(const T & rootData)                                           // Done
{
    root = new Node <T>;                                                                            // Roots parent = leftChild = rightChild = 0L  
    root->nodeData = rootData; 
    currentPosition = root; 
}

template <class T>
RootedBinaryTree<T>::RootedBinaryTree(const RootedBinaryTree<T> & original)                         // done 
{
    root = currentPosition = new Node<T>; 
    *this = original; 
}

template <class T>
RootedBinaryTree<T>::~RootedBinaryTree()                                                            // done
{
    deleteSubtree(root);                                                                            // root will be valid because of our constructor and other methods
    root = currentPosition = 0L;    
}

template <class T>
void RootedBinaryTree<T>::toRoot()                                                                  // Done
{
    currentPosition = root; 
}

template <class T>
bool RootedBinaryTree<T>::moveUp()                                                                  // Done
{
    if(currentPosition->parent == 0L) return false;                                                 // If we are at the root of the tree, we cannot move up it. 
    currentPosition = currentPosition->parent; 
    return true; 
}

template <class T>
bool RootedBinaryTree<T>::moveLeft()                                                                // Done 
{
    if(currentPosition->leftChild == 0L) return false; 
    currentPosition = currentPosition->leftChild; 
    return true; 
}

template <class T>
bool RootedBinaryTree<T>::moveRight()                                                               // Done 
{
    if(currentPosition->rightChild == 0L) return false; 
    currentPosition = currentPosition->rightChild;
    return true; 
}

template <class T>
RootedBinaryTree<T> & RootedBinaryTree<T>::operator=(const RootedBinaryTree<T> & RHS)
{
    if(&RHS == this)
    {
        return *this; 
    }
    this->~RootedBinaryTree();  
    copySubtree(root, RHS.root); 
    currentPosition = RHS.currentPosition; // This is wrong. 

    return *this; 
}

template <class T>
void RootedBinaryTree<T>::combineTrees(const RootedBinaryTree<T> & leftTree, const RootedBinaryTree<T> & rightTree)
{ // Copies leftTree into root's left tree and rightTree into root's right tree.
    if(this == &leftTree || this == &rightTree)
    {
        throw "A rooted binary tree cannot be combined with itself."; 
    }
    if(root->leftChild != 0L) deleteSubtree(root->leftChild);
    if(root->rightChild != 0L) deleteSubtree(root->rightChild);
    copySubtree(root->leftChild, leftTree.root);
    copySubtree(root->rightChild, rightTree.root);
}

template <class T>
void RootedBinaryTree<T>::setNodeData(const T & nodeData)
{
    currentPosition->nodeData = nodeData; 
}

#endif

提前感谢任何回答此问题的人!非常感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

我是通过实现私有方法getPath()来执行此操作,该方法返回从rootcurrentPosition的移动列表(左侧或右侧):

template <class T>
list<bool> RootedBinaryTree<T>::getPath() const
{
  list<bool> path;

  Node<T> *p1=currentPosition;
  Node<T> *p2 = p1->parent;

  while(p2 != 0L)
    {
      if(p2->leftChild==p1)
        path.push_front(true);
      else
        path.push_front(false); // yes, I know this can be done more concisely; I'm going for clarity                   
      p1=p2;
      p2=p1->parent;
    }
  return(path);
}

在另一棵树上调用此方法,获取路径,然后在此树中遵循该路径:

template <class T>
void RootedBinaryTree<T>::followPath(list<bool> path)
{
  currentPosition = root;

  for(list<bool>::const_iterator itr=path.begin(); itr !=path.end() ; ++itr)
    if(*itr)
      moveLeft();
    else
      moveRight();
}