[英]Binary Tree operator overloading and recursion
I was wondering how to overload the == operator for a binary tree to compare if two trees have identical data at same nodes. 我想知道如何为二叉树重载==运算符,以比较两棵树在相同节点上是否具有相同数据。 So far this is what I have:
到目前为止,这就是我所拥有的:
bool TreeType::operator==(const TreeType& otherTree) const
{
if((root == NULL) && (otherTree.root == NULL))
return true; //two null trees are equal
else if((root != NULL) && (otherTree.root != NULL))
{
return((root->info == otherTree.root->info) &&
//this part doesn't actually do anything recursively...
//(root->left == otherTree.root->left) &&
//(root->right == otherTree.root->right))
}
else
return false; //one tree is null the other is not
}
//TREETYPE DECLARATIONS
struct TreeNode;
enum OrderType {PRE_ORDER, IN_ORDER, POST_ORDER};
class TreeType
{
public:
TreeType(); // constructor
~TreeType(); // destructor
TreeType(const TreeType& originalTree);
void operator=(const TreeType& originalTree);
// copy constructor
void MakeEmpty();
bool IsEmpty() const;
bool IsFull() const;
int LengthIs() const;
void RetrieveItem(ItemType& item, bool& found);
void InsertItem(ItemType item);
void DeleteItem(ItemType item);
void ResetTree(OrderType order);
void GetNextItem (ItemType& item, OrderType order,
bool& finished);
void Print(std::ofstream& outFile) const;
bool operator==(const TreeType&) const;
private:
TreeNode* root;
QueType preQue;
QueType inQue;
QueType postQue;
};
//DEFINITIONS
struct TreeNode
{
ItemType info;
TreeNode* left;
TreeNode* right;
};
bool TreeType::IsFull() const
// Returns true if there is no room for another item
// on the free store; false otherwise.
{
TreeNode* location;
try
{
location = new TreeNode;
delete location;
return false;
}
catch(std::bad_alloc exception)
{
return true;
}
}
bool TreeType::IsEmpty() const
// Returns true if the tree is empty; false otherwise.
{
return root == NULL;
}
int CountNodes(TreeNode* tree);
int TreeType::LengthIs() const
// Calls recursive function CountNodes to count the
// nodes in the tree.
{
return CountNodes(root);
}
int CountNodes(TreeNode* tree)
// Post: returns the number of nodes in the tree.
{
if (tree == NULL)
return 0;
else
return CountNodes(tree->left) + CountNodes(tree->right) + 1;
}
void Retrieve(TreeNode* tree,
ItemType& item, bool& found);
void TreeType::RetrieveItem(ItemType& item, bool& found)
// Calls recursive function Retrieve to search the tree for item.
{
Retrieve(root, item, found);
}
void Retrieve(TreeNode* tree,
ItemType& item, bool& found)
// Recursively searches tree for item.
// Post: If there is an element someItem whose key matches item's,
// found is true and item is set to a copy of someItem;
// otherwise found is false and item is unchanged.
{
if (tree == NULL)
found = false; // item is not found.
else if (item info)
Retrieve(tree->left, item, found); // Search left subtree.
else if (item > tree->info)
Retrieve(tree->right, item, found);// Search right subtree.
else
{
item = tree->info; // item is found.
found = true;
}
}
void Insert(TreeNode*& tree, ItemType item);
void TreeType::InsertItem(ItemType item)
// Calls recursive function Insert to insert item into tree.
{
Insert(root, item);
}
void Insert(TreeNode*& tree, ItemType item)
// Inserts item into tree.
// Post: item is in tree; search property is maintained.
{
if (tree == NULL)
{// Insertion place found.
tree = new TreeNode;
tree->right = NULL;
tree->left = NULL;
tree->info = item;
}
else if (item info)
Insert(tree->left, item); // Insert in left subtree.
else
Insert(tree->right, item); // Insert in right subtree.
}
void DeleteNode(TreeNode*& tree);
void Delete(TreeNode*& tree, ItemType item);
void TreeType::DeleteItem(ItemType item)
// Calls recursive function Delete to delete item from tree.
{
Delete(root, item);
}
void Delete(TreeNode*& tree, ItemType item)
// Deletes item from tree.
// Post: item is not in tree.
{
if (item info)
Delete(tree->left, item); // Look in left subtree.
else if (item > tree->info)
Delete(tree->right, item); // Look in right subtree.
else
DeleteNode(tree); // Node found; call DeleteNode.
}
void GetPredecessor(TreeNode* tree, ItemType& data);
void DeleteNode(TreeNode*& tree)
// Deletes the node pointed to by tree.
// Post: The user's data in the node pointed to by tree is no
// longer in the tree. If tree is a leaf node or has only
// non-NULL child pointer the node pointed to by tree is
// deleted; otherwise, the user's data is replaced by its
// logical predecessor and the predecessor's node is deleted.
{
ItemType data;
TreeNode* tempPtr;
tempPtr = tree;
if (tree->left == NULL)
{
tree = tree->right;
delete tempPtr;
}
else if (tree->right == NULL)
{
tree = tree->left;
delete tempPtr;
}
else
{
GetPredecessor(tree->left, data);
tree->info = data;
Delete(tree->left, data); // Delete predecessor node.
}
}
void GetPredecessor(TreeNode* tree, ItemType& data)
// Sets data to the info member of the right-most node in tree.
{
while (tree->right != NULL)
tree = tree->right;
data = tree->info;
}
void PrintTree(TreeNode* tree, std::ofstream& outFile)
// Prints info member of items in tree in sorted order on outFile.
{
if (tree != NULL)
{
PrintTree(tree->left, outFile); // Print left subtree.
outFile info;
PrintTree(tree->right, outFile); // Print right subtree.
}
}
void TreeType::Print(std::ofstream& outFile) const
// Calls recursive function Print to print items in the tree.
{
PrintTree(root, outFile);
}
TreeType::TreeType()
{
root = NULL;
}
void Destroy(TreeNode*& tree);
TreeType::~TreeType()
// Calls recursive function Destroy to destroy the tree.
{
Destroy(root);
}
void Destroy(TreeNode*& tree)
// Post: tree is empty; nodes have been deallocated.
{
if (tree != NULL)
{
Destroy(tree->left);
Destroy(tree->right);
delete tree;
}
}
void TreeType::MakeEmpty()
{
Destroy(root);
root = NULL;
}
void CopyTree(TreeNode*& copy,
const TreeNode* originalTree);
TreeType::TreeType(const TreeType& originalTree)
// Calls recursive function CopyTree to copy originalTree
// into root.
{
CopyTree(root, originalTree.root);
}
void TreeType::operator=
(const TreeType& originalTree)
// Calls recursive function CopyTree to copy originalTree
// into root.
{
{
if (&originalTree == this)
return; // Ignore assigning self to self
Destroy(root); // Deallocate existing tree nodes
CopyTree(root, originalTree.root);
}
}
void CopyTree(TreeNode*& copy,
const TreeNode* originalTree)
// Post: copy is the root of a tree that is a duplicate
// of originalTree.
{
if (originalTree == NULL)
copy = NULL;
else
{
copy = new TreeNode;
copy->info = originalTree->info;
CopyTree(copy->left, originalTree->left);
CopyTree(copy->right, originalTree->right);
}
}
// Function prototypes for auxiliary functions.
void PreOrder(TreeNode*, QueType&);
// Enqueues tree items in preorder.
void InOrder(TreeNode*, QueType&);
// Enqueues tree items in inorder.
void PostOrder(TreeNode*, QueType&);
// Enqueues tree items in postorder.
void TreeType::ResetTree(OrderType order)
// Calls function to create a queue of the tree elements in
// the desired order.
{
switch (order)
{
case PRE_ORDER : PreOrder(root, preQue);
break;
case IN_ORDER : InOrder(root, inQue);
break;
case POST_ORDER: PostOrder(root, postQue);
break;
}
}
void PreOrder(TreeNode* tree,
QueType& preQue)
// Post: preQue contains the tree items in preorder.
{
if (tree != NULL)
{
preQue.Enqueue(tree->info);
PreOrder(tree->left, preQue);
PreOrder(tree->right, preQue);
}
}
void InOrder(TreeNode* tree,
QueType& inQue)
// Post: inQue contains the tree items in inorder.
{
if (tree != NULL)
{
InOrder(tree->left, inQue);
inQue.Enqueue(tree->info);
InOrder(tree->right, inQue);
}
}
void PostOrder(TreeNode* tree,
QueType& postQue)
// Post: postQue contains the tree items in postorder.
{
if (tree != NULL)
{
PostOrder(tree->left, postQue);
PostOrder(tree->right, postQue);
postQue.Enqueue(tree->info);
}
}
void TreeType::GetNextItem(ItemType& item,
OrderType order, bool& finished)
// Returns the next item in the desired order.
// Post: For the desired order, item is the next item in the queue.
// If item is the last one in the queue, finished is true;
// otherwise finished is false.
{
finished = false;
switch (order)
{
case PRE_ORDER : preQue.Dequeue(item);
if (preQue.IsEmpty())
finished = true;
break;
case IN_ORDER : inQue.Dequeue(item);
if (inQue.IsEmpty())
finished = true;
break;
case POST_ORDER: postQue.Dequeue(item);
if (postQue.IsEmpty())
finished = true;
break;
}
}
I have a similar function that takes two TreeNode pointers as parameters but I've been stuck on how to convert it to this function. 我有一个类似的函数,它需要两个TreeNode指针作为参数,但是我一直在坚持将其转换为该函数的方法。
The definition of tree is from a book. 树的定义来自一本书。 I'm just supposed to add the functionality of an overloaded == operator.
我只是应该添加重载==运算符的功能。
It would probably be easiest to add equality operator to the node
class. 将相等运算符添加到
node
类可能是最简单的。
struct node
{
int info;
node * left;
node * right;
friend bool operator==(node const & lhs, node const & rhs)
{
return lhs.info == rhs.info
&& ((lhs.left == 0 && rhs.left == 0)
|| (lhs.left != 0 && rhs.left != 0 && *lhs.left == *rhs.left))
&& ((lhs.right == 0 && rhs.right == 0)
|| (lhs.right != 0 && rhs.right != 0 && *lhs.right == *rhs.right));
}
};
Then you can simply compare root nodes from TreeType::operator==
. 然后,您可以简单地从
TreeType::operator==
比较根节点。
bool TreeType::operator==(const TreeType& otherTree) const
{
return (root == 0 && otherTree.root == 0)
|| (root != 0 && otherTree.root != 0 && *root == *otherTree.root);
}
//value is an integer not an object so that will give you syntax errors.
//This is a more correct way to write this
bool TreeNode::operator==(const TreeNode& node)
{
if (&node == this) return true;
if (left != NULL)
{
if (node.left != NULL) if (*left != *node.left) return false;
else return false;
}
else if (node.left != NULL) return false;
if (right != NULL)
{
if (node.right != NULL) if (*right != *node.right) return false;
else return false;
}
else if (node.right != NULL) return false;
return (value == node.value);
}
Generally the idea in these cases is to have a data structure which is a tree consisting of trees and leaf nodes. 通常,在这些情况下的想法是具有一个数据结构,该数据结构是由树和叶节点组成的树。 Something like
就像是
struct TreeType
{
std::vector<TreeType> subtrees;
std::vector<LeafNodes> leafs;
}
This allows one to define a ==
operator along the lines of 这允许人们定义
==
沿着线操作者
bool TreeType::operator==(const TreeType& rhs) const
{
if each subtree == subtree && each leaf == leaf
then true
else false
}
Here the subtree
comparison will call the ==
operator recursively on the children trees. 在这里,
subtree
比较将在子树上递归调用==
运算符。
EDIT: It would be handy if you provided the exact organization of your TreeType data structure to allow for a better/specific answer. 编辑:如果您提供TreeType数据结构的确切组织以允许更好/特定的答案,那将很方便。
Given this class: 给定此类:
class TreeNode
{
TreeNode* left;
TreeNode* right;
int value;
bool operator==(const TreeNode& node);
};
I would write the ==
operator like this: 我会这样写
==
运算符:
bool TreeNode::operator==(const TreeNode& node)
{
// Are we comparing the node to itself ?
if (&node == this)
return true;
// We have a left node
if (left != NULL)
{
// Does node have a left node too ?
if (value.left != NULL)
{
// Are they different ?
if (!(*left == *value.left))
return false;
} else
// Node has no left node
return false;
} else
{
// We don't have a left node, does node have one ?
if (value.left != NULL)
return false;
}
// We have a right node
if (right != NULL)
{
// Does node have a right node too ?
if (value.right != NULL)
{
// Are they different ?
if (!(*right == *value.right))
return false;
} else
// Node has no right node
return false;
} else
{
// We don't have a right node, does node have one ?
if (value.right != NULL)
return false;
}
// Return true only if we have the same value.
return (value == node.value);
}
Of course the recursion "end-conditions" can be switched for the algorithm to be optimized (checking the value
s first might be more efficient). 当然,可以切换递归“结束条件”以优化算法(首先检查
value
s可能更有效)。
This is left to you as an exercise :D 这留给您作为练习:D
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.