五、【数据结构】二叉树(binary tree)的实现

本文使用C++实现二叉树数据结构,与之前实现的向量、列表、栈和队列不同,树是一种分层结构,虽然树是分层结构,但若附加某种约束,如遍历次序,则树结构也可以转变成线性次序,因此树属于半线性结构。树结构具有非常多的变种,在算法理论和实际应用中,各种树结构扮演着最为关键的角色。

另外,任何有根有序的多叉树,都能转变成二叉树,因此二叉树数据结构具有非常重要的地位。

两种特殊的二叉树:完全二叉树、满二叉树

完全二叉树: 叶子结点只能出现在最底部的两层,且最底层叶节点均处于次底层叶节点的左侧。

满二叉树: 所有叶节点同处于最底层(非底层节点均为内部结点)。

二叉树的实现和列表数据结构有很大的相似性,都需要为相互临近的节点之间维护正确的指针指向。这里二叉树数据结构的实现包括binNode类和binTree类,前者主要描述单个二叉树的结构和对其的操作,而binTree类主要描述整个二叉树的结构和对其进行的操作。

binNode接口列表
操作功能对象
binNode()默认构造函数 
binNode(T e, binNode* p, binNode *lc, binNode *rc, int h)构造函数,设置节点数据,父节点,孩子节点,高度 
~binNode()析构函数 
insertAsLC(const T& e)作为本节点的左孩子插入二叉树节点
insertAsRC(const T& e)作为本节点的右孩子插入二叉树节点
succ()定位在中序遍历中节点v的直接后续二叉树节点
重载运算符==相等判断运算符二叉树节点
重载运算符<小于运算符二叉树节点
binTree接口列表
操作功能对象
binTree()默认构造函数 
~binTree()析构函数 
size()返回二叉树的规模二叉树
empty()判断二叉树是否为空二叉树
root()返回根节点的指针二叉树
insertAsRoot(const T& e)将指定元素作为根节点插入二叉树
insertAsLC(binNode<T>* bn, const T& e)将指定元素插入作为指定节点的左孩子二叉树
insertAsRC(binNode<T>* bn, const T& e)将指定元素插入作为指定节点的右孩子二叉树
attachAsLC(binNode<T>* bn, binTree<T>* &bt)将指定子树插入作为指定节点的左孩子二叉树
attachAsRC(binNode<T>* bn, binTree<T>* &bt)将指定子树插入作为指定节点的右孩子二叉树
updateHeight(binNode<T>* bn)更新节点的高度二叉树
updateHeightAbove(binNode<T>* bn)更新此节点祖先节点的高度(插入或删除节点要执行更新)二叉树
removeAt(binNode<T>* bn)删除节点bn及其后代,并返回删掉的二叉树节点的总数二叉树
remove(binNode<T>* bn)删除以bn为根节点的子树二叉树
secede(binNode<T>* bn)子树分离,将节点bn及其后代从二叉树中分离出来,然后形成一个独立的二叉树二叉树
travPre_R(binNode<T>* bn_r, void(*func)(T& bn))先序遍历(递归版本:简洁易懂)二叉树
travIn_R(binNode<T>* bn_r, void(*func)(T& bn))中序遍历(递归版本:简洁易懂)二叉树
travPost_R(binNode<T>* bn_r, void(*func)(T& bn))后序遍历(递归版本:简洁易懂)二叉树
visitAlongLeftBranch(binNode<T>* bn, void(*func)(T& bn), stack<binNode<T>*> &s)沿着左轮廓线遍历二叉树
travPre_I(binNode<T>* bn_i, void(*func)(T& bn))先序遍历(迭代版本:时间、空间复杂度低)二叉树
goAlongLeftBranch(binNode<T>* bn, stack<binNode<T>*> &s)从当前节点开始,沿着左分支深入入栈二叉树
travIn_I(binNode<T>* bn_i, void(*func)(T& bn))中序遍历(迭代版本:时间、空间复杂度低)二叉树
gotoHLVFL(stack<binNode<T>*> &s)在以s栈顶节点为根的子树中,找到最高左侧可见节点二叉树
travPost_I(binNode<T>* bn_i, void(*func)(T& bn))后序遍历(迭代版本:时间、空间复杂度低)二叉树
travLevel(binNode<T>* bn_i, void(*func)(T& bn))层次遍历二叉树

(1) binNode.h

#pragma once
#define stature(p) ((p)?(p)->height:-1)  //宏定义不要忘记带括号
#define NULL 0
template<typename T> struct binNode
{
	//成员变量
	T data;
	binNode<T> *parent, *lc, *rc;   //指向父类,左孩子右孩子的指针
	int height;  //高度
	//构造函数
	binNode() :data(NULL), lc(nullptr), rc(nullptr), height(0) {}
	binNode(T e, binNode* p = nullptr, binNode *lc = nullptr, binNode *rc = nullptr, int h = 0) :
		data(e), parent(p), lc(lc), rc(rc), height(h) {}
	//析构函数
	~binNode() {}

	//成员函数
	binNode<T>* insertAsLC(const T& e);    //作为本节点的左孩子插入
	binNode<T>* insertAsRC(const T& e);    //作为本节点的右孩子插入
	int size();    //返回以本节点为root的二叉树的规模
	binNode<T>* succ();     //定位在中序遍历中节点v的直接后续
	//重载运算符
	bool operator==(const binNode<T>& bn);  //等于运算符
	bool operator<(const binNode<T>& bn);   //小于运算符
};

template<typename T> binNode<T>* binNode<T>::insertAsLC(const T& e)
{
	return lc = new binNode<T>(e, this);
}

template<typename T> binNode<T>* binNode<T>::insertAsRC(const T& e)
{
	return rc = new binNode<T>(e, this);
}

template<typename T> int binNode<T>::size()
{
	int n = 0;
	if (lc&&rc)
		n = 1 + lc->size() + rc->size();
	if (lc && (!rc))
		n = 1 + lc->size();
	if ((!lc) && rc)
		n = 1 + rc->size();
	if ((!lc) && (!rc))
		return 1;       //递归基
	return n;
}

template<typename T> bool binNode<T>::operator==(const binNode<T>& bn)
{
	return data == bn.data;
}

template<typename T> bool binNode<T>::operator<(const binNode<T>& bn)
{
	return data < bn.data;
}

template<typename T> binNode<T>* binNode<T>::succ()
{
	binNode<T>* s = this;   //记录后续的临时变量
	if (rc)   //若有右孩子,则直接后继一定在右子树中的最左边
	{
		s = rc;
		while (s->lc) s = s->lc;
	}
	else   //若没有右孩子,则直接后继是将当前节点包含在左子树中的最低祖先
	{
		while ((s->parent->lc) != s)
			s = s->parent;
		s = s->parent;
	}
	return s;
}

(2) binTree.h

#pragma once
#include"binNode.h"
#include"stack.h"
#include"queue.h"

#define max(a,b) (((a)>=(b))?(a):(b))

template<typename T> class binTree
{
protected:
	//成员变量
	int _size;        //二叉树规模
	binNode<T>* _root;//根节点指针

public:
	//构造函数
	binTree() :_size(0), _root(nullptr) {}
	
	//析构函数
	~binTree();   //删除掉所有的子二叉树
	
	//成员函数
	int size();   //返回二叉树规模
	bool empty(); //判断二叉树是否为空 
	binNode<T>* root();  //返回根节点的指针
	binNode<T>* insertAsRoot(const T& e);  //将指定元素插入作为根节点
	binNode<T>* insertAsLC(binNode<T>* bn, const T& e);  //将指定元素插入作为指定节点的左孩子
	binNode<T>* insertAsRC(binNode<T>* bn, const T& e);  //将指定元素插入作为指定节点的右孩子
	binNode<T>* attachAsLC(binNode<T>* bn, binTree<T>* &bt);  //将指定子树插入作为指定节点的左孩子
	binNode<T>* attachAsRC(binNode<T>* bn, binTree<T>* &bt);  //将指定子树插入作为指定节点的右孩子
	virtual int updateHeight(binNode<T>* bn);         //更新节点的高度
	void updateHeightAbove(binNode<T>* bn);   //更新此节点祖先节点的高度(插入或删除节点要执行更新)

	int removeAt(binNode<T>* bn);       //删除节点bn及其后代,并返回删掉的二叉树节点的总数
	int remove(binNode<T>* bn);   //删除以bn为根节点的子树
	binTree<T>* secede(binNode<T>* bn);   //子树分离,将节点bn及其后代从二叉树中分离出来,然后形成一个独立的二叉树

	void travPre_R(binNode<T>* bn_r, void(*func)(T& bn));  //先序遍历(递归版本:简洁易懂)
	void travIn_R(binNode<T>* bn_r, void(*func)(T& bn));  //中序遍历(递归版本:简洁易懂)
	void travPost_R(binNode<T>* bn_r, void(*func)(T& bn));  //后序遍历(递归版本:简洁易懂)

	void visitAlongLeftBranch(binNode<T>* bn, void(*func)(T& bn), stack<binNode<T>*> &s);  //沿着左轮廓线遍历
	void travPre_I(binNode<T>* bn_i, void(*func)(T& bn));//先序遍历(迭代版本:时间、空间复杂度低)
	void goAlongLeftBranch(binNode<T>* bn, stack<binNode<T>*> &s); //从当前节点开始,沿着左分支深入入栈
	void travIn_I(binNode<T>* bn_i, void(*func)(T& bn));//中序遍历(迭代版本:时间、空间复杂度低)
	void gotoHLVFL(stack<binNode<T>*> &s);   //在以s栈顶节点为根的子树中,找到最高左侧可见节点
	void travPost_I(binNode<T>* bn_i, void(*func)(T& bn));//后序遍历(迭代版本:时间、空间复杂度低)

	void travLevel(binNode<T>* bn_i, void(*func)(T& bn));  //层次遍历

};

template<typename T> binTree<T>::~binTree()
{
	if (_size)
		remove(_root);
}

template<typename T> int binTree<T>::size()
{
	return _size;
}

template<typename T> bool binTree<T>::empty()
{
	return _root ? true : false;
}

template<typename T> binNode<T>* binTree<T>::root()
{
	return _root;
}

template<typename T> binNode<T>* binTree<T>::insertAsRoot(const T& e)
{
	if (_root) return nullptr;
	_size = 1;
	return	_root = new binNode<T>(e);
}

template<typename T> binNode<T>* binTree<T>::insertAsLC(binNode<T>* bn, const T& e)
{
	if (bn->lc) return nullptr;   //若左孩子已经存在则返回
	_size++;
	bn->lc = new binNode<T>(e, bn);
	updateHeightAbove(bn->lc);
	return bn->lc;
}

template<typename T> binNode<T>* binTree<T>::insertAsRC(binNode<T>* bn, const T& e)
{
	if (bn->rc) return nullptr;   //若右孩子已经存在则返回
	_size++;
	bn->rc = new binNode<T>(e, bn);
	updateHeightAbove(bn->rc);
	return bn->rc;
}

template<typename T> binNode<T>* binTree<T>::attachAsLC(binNode<T>* bn, binTree<T>* &bt)
{
	if (bn->lc) return nullptr;
	bn->lc = bt->root();
	bt->root()->parent = bn;
	updateHeightAbove(bn->lc);
	_size += bt->size();
	//释放bt
	bt->_root = nullptr;
	bt->_size = 0;
	//release(bt);
	bt = nullptr;
	return bn->lc;
}

template<typename T> binNode<T>* binTree<T>::attachAsRC(binNode<T>* bn, binTree<T>* &bt)
{
	if (bn->rc) return nullptr;
	bn->rc = bt->root();
	bt->root()->parent = bn;
	updateHeightAbove(bn->rc);
	_size += bt->size();
	//释放bt
	bt->_root = nullptr;
	bt->_size = 0;
	bt = nullptr;
	return bn->rc;
}

template<typename T> int binTree<T>::updateHeight(binNode<T>* bn)
{	
	return bn->height = (1 + max(stature(bn->lc), stature(bn->rc)));
}

template<typename T> void binTree<T>::updateHeightAbove(binNode<T>* bn)
{

	while (bn)
	{
		updateHeight(bn);
		bn = bn->parent;
	}
}

template<typename T> int binTree<T>::removeAt(binNode<T>* bn)
{
	int n = 0;
	if (bn == nullptr) return 0;
	n = 1 + removeAt(bn->lc) + removeAt(bn->rc);
	delete bn;
	return n;
}

template<typename T> int binTree<T>::remove(binNode<T>* bn)          
{
	if (bn != _root)
	{
		((bn->parent->lc) == bn) ? (bn->parent->lc) = nullptr : (bn->parent->rc) = nullptr;
	}
	binNode<T>* bp = bn->parent;
	int n = removeAt(bn);
	updateHeightAbove(bp);
	_size -= n;
	return n;
}

template<typename T> binTree<T>* binTree<T>::secede(binNode<T>* bn)
{
	//首先清除原二叉树与待删除子树的关联
	if (bn != _root)
	{
		((bn->parent->lc) == bn) ? (bn->parent->lc) = nullptr : (bn->parent->rc) = nullptr;
	}
	//更新height
	binNode<T>* bp = bn->parent;
	updateHeightAbove(bp);

	//封装成新二叉树
	binTree<T>* bt = new binTree<T>();
	bt->_root = bn;
	bn->parent = nullptr;
	//更新size
	bt->_size = bn->size();
	_size -= bt->_size;

	//特殊情况处理
	if (_root = bn)
		_root = nullptr;
	return bt;
}

template<typename T> void binTree<T>::travPre_R(binNode<T>* bn_r, void(*func)(T& bn))
{
	if (!bn_r) return;
	func(bn_r->data);
	travPre_R(bn_r->lc, func);
	travPre_R(bn_r->rc, func);
}


template<typename T> void binTree<T>::travIn_R(binNode<T>* bn_r, void(*func)(T& bn))
{
	if (!bn_r) return;
	travIn_R(bn_r->lc, func);
	func(bn_r->data);
	travIn_R(bn_r->rc, func);
}


template<typename T> void binTree<T>::travPost_R(binNode<T>* bn_r, void(*func)(T& bn))
{
	if (!bn_r) return;
	travPost_R(bn_r->lc, func);
	travPost_R(bn_r->rc, func);
	func(bn_r->data);
}

template<typename T> void binTree<T>::visitAlongLeftBranch(binNode<T>* bn, void(*func)(T& bn), stack<binNode<T>*> &s)
{
	while (bn)
	{
		func(bn->data);
		s.push(bn->rc);  //右孩子入栈
		bn = bn->lc;     //沿着左边沿遍历
	}
}

template<typename T> void binTree<T>::travPre_I(binNode<T>* bn_i, void(*func)(T& bn))
{
	stack<binNode<T>*> S;
	while (true)
	{
		visitAlongLeftBranch(bn_i, func, S);  //遍历且入栈
		if (S.empty()) break;
		bn_i = S.pop();
	}
}

template<typename T> void binTree<T>::goAlongLeftBranch(binNode<T>* bn, stack<binNode<T>*> &s)
{
	while (bn)
	{
		s.push(bn);
		bn = bn->lc;
	}
}

template<typename T> void binTree<T>::travIn_I(binNode<T>* bn_i, void(*func)(T& bn))
{
	stack<binNode<T>*> S;
	while (true)
	{
		goAlongLeftBranch(bn_i, S);
		if (S.empty()) break;
		bn_i = S.pop();
		func(bn_i->data);
		bn_i = bn_i->rc;
	}
}

template<typename T> void binTree<T>::gotoHLVFL(stack<binNode<T>*> &s)
{
	while (binNode<T>* bn_i = s.top())
	{
		if (bn_i->lc)
		{
			if (bn_i->rc)
				s.push(bn_i->rc);
			s.push(bn_i->lc);
		}
		else
		{
			s.push(bn_i->rc);
		}
	}
	s.pop();
}

template<typename T> void binTree<T>::travPost_I(binNode<T>* bn_i, void(*func)(T& bn))
{
	stack<binNode<T>*> S;
	if (bn_i)
		S.push(bn_i);
	while (!S.empty())
	{
		if (S.top() != bn_i->parent)
			gotoHLVFL(S);
		bn_i = S.pop();
		func(bn_i->data);
	}
}
template<typename T> void binTree<T>::travLevel(binNode<T>* bn_i, void(*func)(T& bn))
{
	queue<binNode<T>*> q;
	q.enqueue(bn_i);
	while (!q.empty())  //队列非空
	{
		bn_i = q.dequeue();
		func(bn_i->data);
		if(bn_i->lc)
			q.enqueue(bn_i->lc);
		if(bn_i->rc)
			q.enqueue(bn_i->rc);
	}
}

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值