c++模板实现二叉树,线索化,线索化遍历,非递归遍历及一些基本操作

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为空(未压栈) 此时需
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值