在有根的二进制树模板类中重载了operator=()

Overloading opertator=() in rooted binary tree template class

本文关键字:重载 operator 二进制      更新时间:2023-10-16

我正在编写一个名为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树中找到与RHS树中的currentPosition Node *相对应的节点。

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

我的想法是创建一个空字符串,并使用某种深度优先搜索算法从根开始遍历RHS,直到找到currentPosition,如果我沿着树向左走,则在字符串末尾附加一个0,如果我顺着树向右走,则附加一个1,然后使用该字符串遍历*this树,这应该将我带到相应的CCD_ 17。然而,我知道一定有更好的方法(部分来自直觉,部分是因为我的教练告诉我有更好的方式哈哈)。

以下是相关文件:

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

提前感谢任何回答这个问题的人!非常感谢你的帮助。

我会通过实现一个私有方法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();
}