实现功能
本文代码实现了二叉树的以下操作:
- 无返回值的流创建。
- 带返回值的流创建。
- 无返回值的字符串创建。
- 带返回值的字符串创建。
- 前序、中序、后序递归遍历二叉树。
- 前序、中序、后序迭代遍历二叉树。
- 拷贝二叉树。
- 求二叉树大小。
- 求二叉树高度。
- 查找二叉树中的某个元素。
- 查找二叉树某个节点的父节点。
- 查找二叉树中某热节点的子节点。
- 清空二叉树。
- 比较两棵二叉树。
- 打印某个二叉树节点。
- 等等。
测试
- 功能测试:文中所有代码均通过少量功能测试,并贴出了部分测试代码。代码未进行大量用例测试。
- 边界值测试:未进行边界值测试。
- 特殊输入测试:未进行特殊输入测试。
欢迎交流讨论,欢迎批评指正!
核心代码
#ifndef _BINARY_TREE_H
#define _BINARY_TREE_H
#include<iostream>
#include<stack>
#include<queue>
#include<assert.h>
template<typename T>
class BinaryTree;
template<typename T>
class BinaryTreeNode
{
friend BinaryTree<T>;
public:
BinaryTreeNode() : data(T()),left(nullptr), right(nullptr) {}
BinaryTreeNode(T _data, BinaryTreeNode<T> * left = nullptr, BinaryTreeNode<T> * right = nullptr)
: data(_data), left(nullptr), right(nullptr) {}
private:
T data;
BinaryTreeNode<T> * left;
BinaryTreeNode<T> * right;
};
template<typename T>
class BinaryTree
{
typedef BinaryTreeNode<T> NodeType;
public:
BinaryTree() = default;
BinaryTree(const T& ref) : refval(ref) {}
BinaryTree(const BinaryTree &);
~BinaryTree();
public:
// create binary by cin/string
void createBT();
void createBT(const char *&);
NodeType * createBT_Ret();
NodeType * createBT_Ret(const char *&);
// traverse recur/iter
void preorderTraverse_Recur() const;
void inorderTraverse_Recur() const;
void postorderTraverse_Recur() const;
void preorderTraverse_Iter() const;
void inorderTraverse_Iter() const;
void postorderTraverse_Iter() const;
void levelTraverse() const;
void zigzagTraverse() const;
// get size of tree
size_t size() const;
// get height of tree
size_t height() const;
// get child node
NodeType * leftChild(const NodeType *) const;
NodeType * rightChild(const NodeType *) const;
// get parent node
NodeType * parent(const NodeType *) const;
// find given value node;
NodeType * find(const T &) const;
// judge if two trees are same
bool equal(BinaryTree &) const;
// print tree node
void print(const NodeType *) const;
// clear the tree
void makeEmpty();
protected:
NodeType * _copyTree(NodeType *);
void _createBT(NodeType *&);
void _createBT(NodeType *&, const char *&);
NodeType * _createBT_Ret();
NodeType * _createBT_Ret(const char *&);
void _preorderTraverse_Recur(NodeType *) const;
void _inorderTraverse_Recur(NodeType *) const;
void _postorderTraverse_Recur(NodeType *) const;
void _preorderTraverse_Iter(NodeType *) const;
void _inorderTraverse_Iter(NodeType *) const;
void _postorderTraverse_Iter(NodeType *) const;
void _levelTraverse(NodeType *) const;
void _zigzagTraverse(NodeType *) const;
size_t _size(NodeType *) const;
size_t _height(NodeType *) const;
NodeType * _parent(NodeType *, const NodeType *) const;
NodeType * _find(NodeType *, const T &) const;
bool _equal(NodeType *, NodeType *) const;
void _makeEmpty(NodeType *);
private:
T refval;
NodeType * root;
};
//******************** public interface ********************
////////////////////////////////////////////////////////////
template<typename T>
BinaryTree<T>::BinaryTree(const BinaryTree & bt)
{
root = _copyTree(bt.root);
}
template<typename T>
BinaryTree<T>::~BinaryTree()
{
makeEmpty();
root = nullptr;
}
////////////////////////////////////////////////////////////
template<typename T>
void BinaryTree<T>::makeEmpty()
{
_makeEmpty(root);
}
template<typename T>
void BinaryTree<T>::createBT()
{
_createBT(root);
}
template<typename T>
void BinaryTree<T>::createBT(const char *& str)
{
_createBT(root, str);
}
template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::createBT_Ret()
{
return _createBT_Ret();
}
template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::createBT_Ret(const char *& str)
{
return _createBT_Ret(str);
}
template<typename T>
void BinaryTree<T>::preorderTraverse_Recur() const
{
_preorderTraverse_Recur(root);
}
template<typename T>
void BinaryTree<T>::inorderTraverse_Recur() const
{
_inorderTraverse_Recur(root);
}
template<typename T>
void BinaryTree<T>::postorderTraverse_Recur() const
{
_postorderTraverse_Recur(root);
}
template<typename T>
void BinaryTree<T>::preorderTraverse_Iter() const
{
_preorderTraverse_Iter(root);
}
template<typename T>
void BinaryTree<T>::inorderTraverse_Iter() const
{
_inorderTraverse_Iter(root);
}
template<typename T>
void BinaryTree<T>::postorderTraverse_Iter() const
{
_postorderTraverse_Iter(root);
}
template<typename T>
void BinaryTree<T>::levelTraverse() const
{
_levelTraverse(root);
}
template<typename T>
void BinaryTree<T>::zigzagTraverse() const
{
_zigzagTraverse(root);
}
template<typename T>
size_t BinaryTree<T>::size() const
{
return _size(root);
}
template<typename T>
size_t BinaryTree<T>::height() const
{
return _height(root);
}
template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::leftChild(const NodeType * current) const
{
return current ? current->left : nullptr;
}
template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::rightChild(const NodeType * current) const
{
return current ? current->right : nullptr;
}
template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::parent(const NodeType * givenNode) const
{
return _parent(root, givenNode);
}
template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::find(const T & key) const
{
return _find(root, key);
}
template<typename T>
bool BinaryTree<T>::equal(BinaryTree & bt) const
{
return _equal(root, bt.root);
}
template<typename T>
void BinaryTree<T>::print(const NodeType * current) const
{
if(current)
std::cout << current->data;
}
//******************** protected interface ********************
template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::_copyTree(NodeType * current)
{
if(!current) return nullptr;
NodeType *temp = new NodeType(current->data);
assert(temp);
temp->left = _copyTree(current);
temp->right = _copyTree(current);
return temp;
}
template<typename T>
void BinaryTree<T>::_makeEmpty(NodeType * current)
{
if(current)
{
_makeEmpty(current->left);
_makeEmpty(current->right);
delete current;
}
}
//////////////////////////////////////////////////////////
template<typename T>
void BinaryTree<T>::_createBT(NodeType *& current)
{
T element;
std::cin >> element;
if(refval == element)
current = nullptr;
else
{
current = new NodeType(element);
assert(current);
_createBT(current->left);
_createBT(current->right);
}
}
template<typename T>
void BinaryTree<T>::_createBT(NodeType *& current, const char *& str)
{
if(refval == *str)
current = nullptr;
else
{
current = new NodeType(*str);
assert(current);
_createBT(current->left, ++str);
_createBT(current->right, ++str);
}
}
template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::_createBT_Ret()
{
T element;
std::cin >> element;
if(refval == element) return nullptr;
NodeType *temp = new NodeType(element);
assert(temp);
temp->left = _createBT_Ret();
temp->right = _createBT_Ret();
return temp;
}
template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::_createBT_Ret(const char *& str)
{
if(refval == str) return nullptr;
NodeType * temp = new NodeType(*str);
assert(temp);
temp->left = _createBT_Ret(++str);
temp->right = _createBT_Ret(++str);
return temp;
}
template<typename T>
void BinaryTree<T>::_preorderTraverse_Recur(NodeType * current) const
{
if(current)
{
std::cout << current->data << " ";
_preorderTraverse_Recur(current->left);
_preorderTraverse_Recur(current->right);
}
}
template<typename T>
void BinaryTree<T>::_inorderTraverse_Recur(NodeType * current) const
{
if(current)
{
_inorderTraverse_Recur(current->left);
std::cout << current->data << " ";
_inorderTraverse_Recur(current->right);
}
}
template<typename T>
void BinaryTree<T>::_postorderTraverse_Recur(NodeType * current) const
{
if(current)
{
_postorderTraverse_Recur(current->left);
_postorderTraverse_Recur(current->right);
std::cout << current->data << " ";
}
}
template<typename T>
void BinaryTree<T>::_preorderTraverse_Iter(NodeType *current) const
{
if(!current) return;
std::stack<NodeType*> stack;
stack.push(current);
while(!stack.empty())
{
NodeType *temp = stack.top();
stack.pop();
std::cout << temp->data << " ";
if(temp->right)
stack.push(temp->right);
if(temp->left)
stack.push(temp->left);
}
}
template<typename T>
void BinaryTree<T>::_inorderTraverse_Iter(NodeType *current) const
{
std::stack<NodeType*> stack;
NodeType *temp = current;
while(temp || !stack.empty())
{
while(temp)
{
stack.push(temp);
temp = temp->left;
}
if(!stack.empty())
{
temp = stack.top();
std::cout << temp->data << " ";
stack.pop();
temp = temp->right;
}
}
}
/*
enum{unvisited, visited};
template<typename T>
void BinaryTree<T>::_postorderTraverse_Iter(NodeType * current) const
{
if(!current) return;
std::stack<std::pair<NodeType*, int>> stack;
stack.push(std::make_pair<current, unvisited>);
while(!stack.empty())
{
NodeType *temp = stack.top().first;
if(stack.top().second == unvisited)
{
stack.top().second = visited;
if(temp->right)
stack.push(std::make_pair<temp->right, unvisited>);
if(temp->left)
stack.push(std::make_pair<temp->left, unvisited>);
}
else
{
std::cout << temp.first << " ";
stack.pop();
}
}
}
*/
template<typename T>
void BinaryTree<T>::_postorderTraverse_Iter(NodeType * current) const
{
if(!current) return;
std::stack<NodeType*> stack;
stack.push(current);
std::stack<NodeType*> stackOfTemp;
while(!stack.empty())
{
NodeType *temp = stack.top();
stack.pop();
stackOfTemp.push(temp);
if(temp->left)
stack.push(temp->left);
if(temp->right)
stack.push(temp->right);
}
while(!stackOfTemp.empty())
{
std::cout << stackOfTemp.top()->data << " ";
stackOfTemp.pop();
}
}
template<typename T>
void BinaryTree<T>::_levelTraverse(NodeType * current) const
{
if(!current) return;
std::queue<NodeType*> queue;
NodeType *temp = current;
queue.push(temp);
while(!queue.empty())
{
temp = queue.front();
std::cout << temp->data << " ";
queue.pop();
if(temp->left)
queue.push(temp->left);
if(temp->right)
queue.push(temp->right);
}
}
template<typename T>
void BinaryTree<T>::_zigzagTraverse(NodeType * current) const
{
if(!current) return;
NodeType *temp = current;
std::stack<NodeType*> stackLeftToRight;
std::stack<NodeType*> stackRightToLeft;
stackLeftToRight.push(temp);
while(!stackLeftToRight.empty() || !stackRightToLeft.empty())
{
while(!stackLeftToRight.empty())
{
temp = stackLeftToRight.top();
std::cout << temp->data << " ";
stackLeftToRight.pop();
if(temp->left)
stackRightToLeft.push(temp->left);
if(temp->right)
stackRightToLeft.push(temp->right);
}
while(!stackRightToLeft.empty())
{
temp = stackRightToLeft.top();
std::cout << temp->data << " ";
stackRightToLeft.pop();
if(temp->right)
stackLeftToRight.push(temp->right);
if(temp->left)
stackLeftToRight.push(temp->left);
}
}
}
template<typename T>
size_t BinaryTree<T>::_size(NodeType *current) const
{
return current ? 1 + _size(current->left) + _size(current->right) : 0;
}
template<typename T>
size_t BinaryTree<T>::_height(NodeType *current) const
{
if(!current) return 0;
size_t heightOfLeft = 1 + _height(current->left);
size_t heightOfRight = 1 + _height(current->right);
return heightOfLeft > heightOfRight ? heightOfLeft : heightOfRight;
}
template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::_parent(NodeType * current, const NodeType *givenNode) const
{
if(!current || !givenNode) return nullptr;
if(current->left == givenNode || current->right == givenNode)
return current;
NodeType * result = _parent(current->left, givenNode);
if(!result)
result = _parent(current->right, givenNode);
return result;
}
template<typename T>
BinaryTreeNode<T> * BinaryTree<T>::_find(NodeType *current, const T & key) const
{
if(!current) return nullptr;
if(current->data == key) return current;
NodeType *result = _find(current->left, key);
if(!result)
result = _find(current->right, key);
return result;
}
template<typename T>
bool BinaryTree<T>::_equal(NodeType *leftRoot, NodeType *rightRoot) const
{
if(!leftRoot && !rightRoot) return true;
if(!leftRoot || !rightRoot) return false;
bool result = (leftRoot == rightRoot)
&& _equal(leftRoot->left, rightRoot->left)
&& _equal(leftRoot->right, rightRoot->right);
return result;
}
#endif
部分测试代码
/********************************************
* Author :
* Email :
* Filename : mainForBinaryTree.cpp
* Creation time : 2018-01-03 00:02:05
* Last modified : 2018-01-03 01:15:40
* Description : ---
*******************************************/
#include<iostream>
#include"BinaryTree.h"
void test1()
{
std::cout << "stream creation test:\n";
BinaryTree<int> *bt = new BinaryTree<int>(-1);
bt->createBT();
std::cout << " levelTraverse(): ";
bt->levelTraverse();
std::cout << "\n";
std::cout << " zigzagTraverse(): ";
bt->zigzagTraverse();
std::cout << "\n";
std::cout << " preorderTraverse_Iter(): ";
bt->preorderTraverse_Iter();
std::cout << "\n";
std::cout << " inorderTraverse_Iter(): ";
bt->inorderTraverse_Iter();
std::cout << "\n";
std::cout << "postorderTraverse_Iter(): ";
bt->postorderTraverse_Iter();
std::cout << "\n";
std::cout << " size(): ";
std::cout << bt->size() << std::endl;
std::cout << " hight(): ";
std::cout << bt->height() << std::endl;
std::cout << " find(): ";
int key = 5;
bt->print(bt->find(key));
std::cout << "\n";
}
void test2()
{
std::cout << "\nstring creation test:\n";
BinaryTree<char> *bt = new BinaryTree<char>('#');
const char * str = "abc##d##e##";
bt->createBT(str);
std::cout << " levelTraverse(): ";
bt->levelTraverse();
std::cout << "\n";
std::cout << " zigzagTraverse(): ";
bt->zigzagTraverse();
std::cout << "\n";
std::cout << " preorderTraverse_Iter(): ";
bt->preorderTraverse_Iter();
std::cout << "\n";
std::cout << " inorderTraverse_Iter(): ";
bt->inorderTraverse_Iter();
std::cout << "\n";
std::cout << "postorderTraverse_Iter(): ";
bt->postorderTraverse_Iter();
std::cout << "\n";
std::cout << " size(): ";
std::cout << bt->size() << std::endl;
std::cout << " hight(): ";
std::cout << bt->height() << std::endl;
std::cout << " find(): ";
char key = 'e';
bt->print(bt->find(key));
std::cout << "\n";
}
int main()
{
test1();
test2();
}