在有根的二进制树模板类中重载了operator=()
Overloading opertator=() in rooted binary tree template class
我正在编写一个名为RootedBinaryTree
的模板类,它具有类似链表的结构,其元素类型为Node
,这是我在下面的头文件中定义的结构。二叉树中的每个节点都有一个parent Node *
,并且可以有leftChild Node *
和rightChild Node *
,也可以没有子节点。(例如:如果你要画一个有根的二叉树,它应该是这样的http://mathworld.wolfram.com/images/eps-gif/CompleteBinaryTree_1000.gif)。
一个有根的二叉树有两个成员:root
和currentPosition
,它们属于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()
来实现这一点,该方法返回从root
到currentPosition
:的移动列表(左或右)
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();
}
- 运算符重载:"operator+"必须采用零个或一个参数
- "operator()"在重载运算符方法中是什么意思,在priority_queue(STL)中用作C++中的比较器?
- 重载的 operator() 在 Cython 中失败
- C++ 继承:基类中重载 operator+ 的 2 次在派生类中无法正常工作
- 当试图交换可变模板类时,如何正确地重载operator=
- 错误:使用复制和交换习惯用法的交换函数中"operator="的重载不明确
- 从 std::ostream 重载 << 运算符时,为什么编译器会给出"too many parameters for this operator function"错误?
- 如何在不重载"operator()"、"std::less"、"std
- 如何在具有动态大小数组的模板化类中重载 operator=
- 重载 operator= 时返回引用和值有什么区别?
- 重载Operator =作为成员函数
- 在 STL 容器中存储具有重载"operator&"的类对象在 C++ 中合法吗?
- 重载operator<对于指向类对象的指针
- 重载operator< & lt;作为会员打印
- c++重载:operator =的重载
- 是否有一种方法可以重载operator=来为右边的函数提供特定的行为?
- 声明一个接受并返回` `流` `的函数有什么用?而不是重载operator<<
- 如何重载operator<<用于c++中的数组
- 重载运算符的模板:错误:重载'operator*'必须至少有一个类或枚举类型的参数
- 为什么在 std::string 上重载"operator <<"不起作用?