#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++)
猜你喜欢
转载自blog.csdn.net/cat1992/article/details/75736199
今日推荐
周排行