c++模板类实现二叉树一些基本操作:前中后 遍历 及其 非递归遍历。 二叉树线索化, 及线索化后采用非递归方式遍历。 层序遍历。 叶子结点个数, k层节点个数, 二叉树深度, 查找元素等。
两个头文件, 一个是线索化有关, 另一个是别的操作
BinaryTree:
#ifndef BINARY_TREE_H_
#define BINARY_TREE_H_
//树这,递归思想很重想(而且,不管是以递归还是非递归解决问题,重要思想是:子问题(按递归子问题思路想,比如只考虑树有左右两个节点的情况下(且都为NULL)怎么处理(或者有两个结点,且都为子节点(即节点后无结点))(再或者只有一个根呢?),再把左右树当新结点(根)采用同样的方法就可以了) 只要理解了这一点,很多题都很好做
#include <queue> //层序遍历
#include <stack> //非递归实现遍历
template<class T>
struct BinaryTreeNode
{
BinaryTreeNode<T>* _left; //<T>
BinaryTreeNode<T>* _right; //<T>
T _date;
BinaryTreeNode( const T& x )
:_date( x )
,_left( NULL )
,_right( NULL )
{}
};
template<class T>
class BinaryTree
{
typedef BinaryTreeNode<T> Node; //<T>,以及这条语句放在类里面(这个Node只是BinaryTreeNode 为了简便用Node,但为防止重命名, 所以放在类里面,而不是外面)
public:
BinaryTree( ) //相当于还是自己写了个 默认的构造函数 只是使用了c++11初始化方式
:_root( NULL )
{}
BinaryTree( T* a, size_t n, const T& invalid = T( ) )//成员函数不易含有递归
{
size_t index = 0;
_root = CreateTree( a, n, invalid, index );//所以调用这个Fun
}
~BinaryTree( ) //后序最好
{
_Destroy( _root );
}
BinaryTree( const BinaryTree<T>& rhs ) //<T> 深拷贝 //参数const修饰 不可改
{
_root = Copy( rhs._root ); //想想this指针 //指针访问数据成员用-> 对象用.! 傻不傻!? ->用惯了,啥都用->?
}
/* 参数const修饰不可改, but返回的不是const对象, 所以返回值无const */
BinaryTree<T>& operator=( const BinaryTree<T>& rhs )//<T> 想想 t1 = t2 先释放t1原空间,再通过t2构建一棵新树 (即下面写的内容)
{
if ( this != &rhs ) //别忘了检查是否是自己赋值自己
{
_Destroy( _root );
Node* newRoot;
newRoot = Copy( rhs._root );
_root = newRoot;
} //不是返回const对象,所以,返回值别用const修饰 除非是const对象,返回时再用const修饰
return *this;
}; //别用 const 修饰 this 指针
//BinaryTree<T>& operator=( const BinaryTree<T>& rhs )//现代写法 自己写= 则开辟新的空间(根据你的写法)(先delete旧空间,再开辟新空间)( 临时对象就像临时变量一样,传引用不会有 )
//{
// swap( _root, rhs->_root ); //直接 这样写不对吧? rhs->_root 变为 (this)->_root rhs这个被引用的对象不是出问题了吗
// return *this; //传对象时才构建临时对象(想临时变量),然后直接赋值(出作用域销毁, 如果是指针则出问题 所以是引用, 不存在临时对象问题)
//} //都是默认的时, t1 = t2. 构造临时对象直接赋值? 参数是啥 引用(直接赋值)还是临时对象(如果自己写了开辟新空间,默认则直接赋值)。 临时对象销毁(参数有指针则出问题,对象销毁都会调用析构函数(此时又牵扯到默认析构函数是什么)),临时对象和t2相同(通过默认拷贝构造创建临时对象,值拷贝). 赋值构造和=(原参数引用)自己写都开辟新空间
void PrevOrder( ) //含有递归的不适宜放在public
{
_PrevOrder( _root );
}
void PrevOrderNonR( ) //前序遍历非递归实现
{
Node* cur = _root;
stack<Node*> s;
while ( (NULL != cur) || (!s.empty( )) )//不只是stack不为空,第一次stack为空(未压栈) 此时需