#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
顺序二叉树的基础操作(C++)
最新推荐文章于 2023-10-06 15:40:30 发布