顺序二叉树的基础操作(C++)

#ifndef _BSTREE_
#define _BSTREE_

template<typename T>
struct BSNode{
	BSNode(T t) :value(t),lchild(nullptr),rchild(nullptr);

	T value;
	BSNode *lchild;
	BSNode *rchild;
	BSNode *parent;
	int LTag;
	int RTag;//0:指向左右孩子的指针;1:指向前驱/后继的线索
};

//二叉查找树类
/*1.BSTree的根节点root,这是唯一的数据成员
2.操作的外部接口与内部实现接口。例如 preOrder()为提供给用户使用的接口,接口声明为public;而preOrder(AVLTreeNode* pnode)是类内部为了递归操作所使用的接口,接口声明为private。*/
template<typename T>
class BSTree
{
public:
	BSTree();
	~BSTree();

	void preOrder();   //前序遍历二叉树
	void inOrder();        //中序遍历二叉树
	void postOrder();   //后序遍历二叉树
	void layerOrder();    //层次遍历二叉树

	BSNode<T>* search_recursion(T key);   //递归查找
	BSNode<T>* search_Iterator(T key);      //迭代查找

	T search_mininum();       //查找最小元素
	T search_maxinum();      //查找最大元素

	BSNode<T>* successor(BSNode<T> *x);      //查找指定节点的后继节点
	BSNode<T>* predecessor(BSNode<T> *x);         //查找指定节点的前驱节点

	void insert(T key);     //插入指定值节点
	void remove(T key);     //删除指定值节点
	void destory();      //销毁二叉树
	void print();           //打印二叉树
	

	void CreateBSTree();  //创建二叉树
	void InTreading();//中序遍历线索化

private:
	BSNode<T> *root;    //根节点
private:
	BSNode<T>* search(BSNode<T> *&p, T key);
	void remove(BSNode<T> *p, T key);
	void preOrder(BSNode<T> *p);
	void postOrder(BSNode<T>* p);
	T search_minimun(BSNode<T>* p);
	T search_maximum(BSNode<T>* p);
	void destory(BSNode<T>* &p);
	void InTreading(BSNode<T> *p);
};

//递归创建二叉树
template<typename T>
void BSTree<T>::CreateBSTree(BSNode<T> *x)
{
	T ch;
	cin >> ch;
	if (ch == '#')
		*x = nullptr;
	else{
		*x = new BSNode<T>(ch);
		CreateBSTree(&(*x)->lchild);
		CreateBSTree(&(*x)->rchild);
	}
}


/*中序遍历线索化二叉树
线索化的意义:充分利用空指针,记住结点的前驱、后继(不同遍历次序,前驱后继不同)*/
template<typename T>
void BSTree<T>::InTreading()
{
	InTreading(root);
}
template<typename T>
void BSTree<T>::InTreading(BSNode<T> *p)
{
	BSNode<T> *pre = new BSNode<T>;
	*pre = nullptr;

	if (p)//递归左子树线索化
	{
		InTreading(p->lchild);//没有左孩子
		if (!p->lchild)
		{
			p->LTag = 1;//前驱线索
			p->lchild = pre;//左孩子指针指向前驱
		}
		if (!pre->rchild)//前驱没有右孩子
		{
			pre->RTag = 1;//后继线索
			pre->rchild = p;//前驱右孩子指针指向后继(当前结点p)
		}
		pre = p;//保持pre指向p的前驱
		InTreading(p->rchild);//递归右子树线索化
	}
}


/*插入新节点:
1.如果是空树,则创建一个新节点,新节点作为根
2.寻找元素合适的插入位置:新元素与当前结点进行比较,若值大于当前结点,则从右子树进行寻找;否则从左子树进行寻找.
3.找到插入位置之后,以元素的值构建新节点,插入二叉排序树中*/
template<typename T>
void BSTree<T>::insert(T key)
{
	BSNode<T> *pparent = nullptr;
	BSNode<T> *pnode = root;

	while (pnode != nullptr)         // 寻找合适的插入位置
	{
		pparent = pnode;
		if (key > pnode->value)
			pnode = pnode->rchild;
		else if (key < pnode->value)
			pnode = pnode->lchild;
		else
			break;
	}

	pnode = new BSNode<T>(key);//以元素的值构建新节点
	if (pparent == nullptr)//如果是空树
		pnode = root; //则新节点为根
	else{
		if (key > pparent->value)
			pparent->rchild = pnode;//否则新节点为其父节点的左孩
		else
			pparent->lchild=pnode;//或右孩
	}
	pnode->parent = pparent;//指明新节点的父节点 
}

/*遍历平衡二叉树:前序遍历、中序遍历、后序遍历*/
/*前序遍历:
若二叉树为空,则空操作返回,否则先访问根节点,然后前序遍历左子树,再前序遍历右子树。(简记为:VLR)*/
template<typename T>
void BSTree<T>::preOrder()
{
	preOrder(root);
};
template<typename T>
void BSTree<T>::preOrder(BSNode<T> *p)
{
	if (p != nullptr)
	{
		cout << p->value << " ";
		preOrder(p->lchild);
		preOrder(p->rchild);
	}
	cout << endl;
}

/*中序遍历:
若二叉树为空,则空操作返回,否则从根节点开始,中序遍历根节点的左子树,然后访问根节点,最后中序遍历右子树。(简记为:LVR)*/
template<typename T>
void BSTree<T>::inOrder()
{
	inOrder(root);
}
template<typename T>
void BSTree<T>::inOrder(BSNode<T> *p)
{
	if (p != nullptr)
	{
		inOrder(p->lchild);
		cout << p->value << " ";
		inOrder(p->rchild);
	}
	cout << endl;
}

/*后序遍历:
若树为空,则返回空操作,否则从左到右先叶子后节点的方式遍历访问左右子树,左右子树都访问结束,才访问根节点。(简称LRV)*/
template<typename T>
void BSTree<T>::postOrder()
{
	postOrder(root)
}
template<typename T>
void BSTree<T>::postOrder(BSNode<T>* p)
{
	if (p != nullptr)
	{
		postOrder(p->lchild);
		postOrder(p->rchild);
		cout << p->value << " ";
	}
	cout << endl;
}

/*前驱:中序遍历
1.它有左子树,则左子树根节点为其前驱节点
2.它没有左子树,且它本身为右子树,则其父节点为其前驱节点
3.它没有左子树,且它本身为左子树,则它的前驱节点为“第一个拥有右子树的父节点”*/
template<typename T>
BSNode<T> *BSTree<T>::predecessor(BSNode<T> *pnode)
{
	if (pnode->lchild != nullptr)
	{
		pnode = pnode->lchild;
		while (pnode->lchild != nullptr)
			pnode = pnode->rchild;
		return pnode;
	}

	BSNode<T>* pparent = pnode->parent;
	while (pparent != nullptr && pparent->lchild == pnode)//如果进入循环,则是第三种情况;否则为第二种情况
	{
		pnode = pparent;
		pparent = pparent->parent;
	}
	return pparent;
}

/*后继:中序遍历
1.它有右子树;则其后继节点为其右子树的最左节点
2.它没有右子树,但它本身是一个左孩子,则后继节点为它的双亲
3.它没有右子树,但它本身是一个右孩子,则其后继节点为“具有左孩子的最近父节点”*/
template<typename T>
BSNode<T>* BSTree<T>::successor(BSNode<T> *pnode)
{
	if (pnode->rchild != nullptr)
	{
		pnode = pnode->rchild;
		while (pnode->lchild != nullptr)
			pnode = pnode->lchild;
		return pnode;
	}

	BSNode<T>* pparent = pnode->parent;
	while (pparent != nullptr && pparent->rchild == pnode)//如果进入循环,则是第三种情况;否则为第二种情况
	{
		pnode = pparent;
		pparent = pparent->parent;
	}
	return pparent;
}

/*删除节点:
1.被删除节点同时有左子树与右子树:将前驱节点的值保存在当前结点,继而删除前驱节点
2.被删除节点只有左子树或只有右子树:用子树替换被删节点
3.被删除节点没有子树:直接删除节点*/
template<typename T>
void BSTree<T>::remove(T key)
{
	remove(root, kye);
}
template<typename T>
void BSTree<T>::remove(BSNode<T>* pnode, T key)
{
	if (pnode != nullptr)
	{
		if (pnode->value == key)
		{
			BSNode<T>* pdel == nullptr;

			if (pnode->lchild == nullptr || pnode->rchild == nullptr)//情况2、3,被删除的节点只有左右子树,或者没有孩子
				pdel = pnode;
			else
				pdel = predecessor(pnode);//情况1:被删除的节点同时又左右子树,则将该节点的前驱的值保存到该节点

			//此时,被删除的节点只有一个孩子(或没有孩子),保存该孩子指针
			BSNode<T>* pchild = nullptr;
			if (pdel->lchild != nullptr)
				pchild = pdel->lchild;
			else if (pdel->rchild != nullptr)
				pchild = pdel->rchild;

			//让孩子指向被删除节点的父节点
			if (pchild != nullptr)
				pchild->parent = pdel->parent;

			//如果要删除的节点是头结点,注意更改root的值
			if (pdel->parent == nullptr)
				root = pchild;
			else if (pdel->parent->lchild == pdel)//如果要删除的节点不是头节点,要注意更改它的双亲节点指向新的孩子节点
				pdel->parent->lchild = pchild;
			else if (pdel->parent->rchild == pdel)
				pdel->parent->rchild = pchild;

			if (pnode->value != pdel->value)
				pnode->value = pdel->value;//将前驱的值代替该节点的值

			delete pdel;
		}
		else if (pnode->value > key)
			remove(pnode->lchild, key);
		else
			remove(pnode->rchild, key);
	}
}

/*查找元素:
元素的查找过程与元素的插入过程一致,也是在不断地与当前结点进行比较,若值比当前节点的值大,则在右子树进行查找,
若值比当前节点的值小,则在左子树进行查找,可以看到这是一个很适合递归操作的过程。
而由于二叉排序树这种左小右大的节点特征,也很容易进行非递归查找*/
//非递归
template<typename T>
BSNode<T>* BSTree<T>::search_Iterator(T key)
{
	BSNode<T>* pnode = root;
	while (pnode!=nullptr)
	{
		if (key == pnode->value)//找到
			return pnode;
		else if (key > pnode->value)//大了,在节点右子树查找
			pnode = pnode->rchild;
		else//小了,在节点左子树查找
			pnode = pnode->lchild;
	}
	return nullptr;
}

//递归
template<typename T>
BSNode<T>* BSTree<T>::search_recursion(T key)
{
	return search(root, key);
}
template<typename T>
BSNode<T>* BSTree<T>::search(BSNode<T>* pnode, T key)
{
	if (pnode != nullptr)
	{
		if (key == pnode->value)
			return pnode;
		else if (key > pnode->value)
			return search(pnode->lchild, key);
		else
			return search(pnode->rchild, key);
	}
	else
		return nullptr;
}

//查找最值元素
//最小元素
template<typename T>
T BSTree<T>::search_minimun()
{
	return search_minimun(root);
}
template<typename T>
T BSTree<T>::search_minimun(BSNode<T>* pnode)
{
	if (pnode->lchild != nullptr)
		return search_minimun(pnode->lchild);
	return pnode->value;
}
//最大元素
template<typename T>
T BSTree<T>::search_maximun()
{
	return search_maximun(root);
}
template<typename T>
T BSTree<T>::search_maximun(BSNode<T>* pnode)
{
	if (pnode->rchild != nullptr)
		return search_maximun(pnode->rchild);
	return pnode->value;
}

//销毁二叉树:使用遍历递归销毁二叉树
template<typename T>
void BSTree<T>::destory()
{
	return destory(root);
}
template<typename T>
void BSTree<T>::destory(BSNode<T>* pnode)
{
	if (p != nullptr)//后序
	{
		if (pnode->lchild != nullptr)
			destory(pnode->lchild);
		if (pnode->rchild != nullptr)
			destory(pnode->rchild);
		delete pnode;
		pnode = nullptr;
	}
}
#endif

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值