《C++实现数据结构》:二叉搜索树
2017-03-22 15:05
375 查看
设结点由关键字值表征,假定所有结点的关键字值各不相同,二叉搜索树或者是一棵空二叉树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的关键字值均不小于根结点的关键字值。
(2)若右子树不空,则右子树上所有结点的关键字值均大于根结点的关键字值。
(3)左、右子树也分别是二叉搜索树。
具体实现见代码,相关注释已写。
测试用例:
为了便于观察,画出树的图形如下。
运行结果如下:
(1)若左子树不空,则左子树上所有结点的关键字值均不小于根结点的关键字值。
(2)若右子树不空,则右子树上所有结点的关键字值均大于根结点的关键字值。
(3)左、右子树也分别是二叉搜索树。
具体实现见代码,相关注释已写。
// // Created by huxijie on 17-3-21. // 二叉搜索树 #include <iostream> #include <stack> #include <queue> using namespace std; //二叉树结点类 template <typename T> struct BTNode{ T elemet; BTNode<T>* lChild,*rChild; BTNode() { lChild = rChild = NULL; } BTNode(const T& x) { elemet = x; lChild = rChild = NULL; } operator T() const { return elemet; } BTNode(const T& x,BTNode<T>* l, BTNode<T> *r) { elemet = x; lChild = l; rChild = r; } }; //二叉搜索树类 template <typename T> class BSTree{ protected: BTNode<T>* root; private: bool Search(BTNode<T> *p,T& x) const; void Clear(BTNode<T> *p); void PreOrder(void (*Visit)(T &x),BTNode<T> *r); void InOrder(void (*Visit)(T &x),BTNode<T> *r); void PostOrder(void (*Visit)(T &x),BTNode<T> *r); void LayerOrder(void (*Visit)(T &x), BTNode<T> *r); public: BSTree() { root = NULL; } ~BSTree(); bool Search(T x)const; //搜索是否存在x bool Insert(T x); //插入x bool Remove(T x); //删去x void PreOrder(void (*Visit)(T &x)); //先序遍历 void InOrder(void (*Visit)(T &x)); //中序遍历 void PostOrder(void (*Visit)(T &x)); //后序遍历 void LayerOrder(void (*Visit)(T &x)); //层次遍历 }; template <typename T> BSTree<T>::~BSTree() { Clear(root); } template <typename T> void BSTree<T>::Clear(BTNode<T> *p) { if (p == NULL) { return; } else { Clear(p->lChild); Clear(p->rChild); delete (p); } } //访问元素的函数,作为参数传入遍历函数中 template <typename T> void Visit(T &x) { cout << x << " "; } ////递归实现先序遍历 //template <typename T> //void BSTree<T>::PreOrder(void (*Visit)(T &x),BTNode<T> *r) { // if (r) { // Visit(r->elemet); // PreOrder(Visit, r->lChild); // PreOrder(Visit, r->rChild); // } //} //非递归实现先序遍历 template <typename T> void BSTree<T>::PreOrder(void (*Visit)(T &x),BTNode<T> *r) { if (r == NULL) { return; } BTNode<T>* p = r; stack<BTNode<T> *> mystack; while (p != NULL || !mystack.empty()) { //边遍历边打印,并存入栈中,以后需要通过这些结点进入右子树 while (p != NULL) { Visit(p->elemet); mystack.push(p); p = p->lChild; } //当p为空时,说明根和左子树已经遍历完了,需要进入右子树了 if (!mystack.empty()) { p = mystack.top(); mystack.pop(); p = p->rChild; } } } template <typename T> void BSTree<T>::PreOrder(void (*Visit)(T &)) { PreOrder(Visit, root); } ////递归实现中序遍历 //template <typename T> //void BSTree<T>::InOrder(void (*Visit)(T &), BTNode<T> *r) { // if (r) { // InOrder(Visit, r->lChild); // Visit(r->elemet); // InOrder(Visit, r->rChild); // } //} //非递归实现中序遍历 template <typename T> void BSTree<T>::InOrder(void (*Visit)(T &), BTNode<T> *r) { if (r == NULL) { return; } BTNode<T> *p = r; stack<BTNode<T>*> mystack; while (p != NULL || !mystack.empty()) { //一直遍历到最后一棵左子树,边遍历边保存根结点到栈中 while (p != NULL) { mystack.push(p); p = p->lChild; } //当p为空时,说明已经到达最后一棵左子树了,这时需要出栈了 if (!mystack.empty()) { p = mystack.top(); mystack.pop(); Visit(p->elemet); //进入右子树,开始新的一轮左子树遍历 p = p->rChild; } } } template <typename T> void BSTree<T>::InOrder(void (*Visit)(T &)) { InOrder(Visit, root); } ////递归实现后序遍历 //template <typename T> //void BSTree<T>::PostOrder(void (*Visit)(T &), BTNode<T> *r) { // if (r) { // PostOrder(Visit, r->lChild); // PostOrder(Visit, r->rChild); // Visit(r->elemet); // } //} //非递归实现后序遍历 template <typename T> void BSTree<T>::PostOrder(void (*Visit)(T &), BTNode<T> *r) { if (r == NULL) { return; } stack<BTNode<T>*> mystack; BTNode<T>* pCur = r; //当前访问结点 BTNode<T>* pLast = NULL; //上次访问结点 //一直遍历到最后一棵左子树,边遍历边保存根结点到栈中 while (pCur != NULL) { mystack.push(pCur); pCur = pCur->lChild; } //已经遍历到最后一棵左子树了,接下来从栈中取结点 while (!mystack.empty()) { pCur = mystack.top(); mystack.pop(); //一个根结点被访问的前提是:无右子树或者右子树已被访问过 if (pCur->rChild == NULL || pCur->rChild == pLast) { Visit(pCur->elemet); //修改最近被访问的结点 pLast = pCur; } else { //先进入右子树 mystack.push(pCur); //根结点重新入栈 pCur = pCur->rChild; //进入右子树 while (pCur != NULL) { //开始在右子树中一直遍历到最后一棵左子树 mystack.push(pCur); pCur = pCur->lChild; } } } } template <typename T> void BSTree<T>::PostOrder(void (*Visit)(T &)) { PostOrder(Visit, root); } //用队列实现层次遍历 template <typename T> void BSTree<T>::LayerOrder(void (*Visit)(T &x),BTNode<T> *r) { if (!r) { return; } queue<BTNode<T>*> myqueue; BTNode<T> *p = r; while (p != NULL || !myqueue.empty()) { if (p != NULL) { Visit(p->elemet); myqueue.push(p->lChild); myqueue.push(p->rChild); } p = myqueue.front(); myqueue.pop(); } } template <typename T> void BSTree<T>::LayerOrder(void (*Visit)(T &)) { LayerOrder(Visit, root); } ////搜索的递归算法 //template <typename T> //bool BSTree<T>::Search(BTNode<T> *p, T &x) const { // if (!p) { // return false; // } else if (x < p->elemet) { // return Search(p->lChild, x); // } else if (x > p->elemet) { // return Search(p->rChild, x); // } else { // return true; // } //} //搜索的迭代算法 template <typename T> bool BSTree<T>::Search(BTNode<T> *p, T &x) const { while (p) { if (x < p->elemet) { p = p->lChild; } else if (x > p->elemet) { p = p->rChild; } else { return true; } } return false; } template <typename T> bool BSTree<T>::Search(T x) const { return Search(root, x); } template <typename T> bool BSTree<T>::Insert(T x) { BTNode<T> *p = root; BTNode<T> *q = NULL; while (p) { q = p; if (x < p->elemet) { p = p->lChild; } else if (x > p->elemet) { p = p->rChild; } else { cout<<"Duplicate"<<endl; return false; } } p = new BTNode<T>(x); if (!root) { root = p; } else if (x < q->elemet) { q->lChild = p; } else { q->rChild = p; } //新结点p连到q结点,成为q的孩子 return true; } template <typename T> bool BSTree<T>::Remove(T x) { BTNode<T> *p = root, *q, *r, *s, *c; q = r = s = c = NULL; while (p && p->elemet != x) { q = p; //q指向p的父结点 if (x < p->elemet) { p = p->lChild; } else if (x > p->elemet) { p = p->rChild; } } if (!p) { cout<<"Not exist"<<endl; return false; } //p是逻辑上待删除的结点 //如果结点p有两棵非空子树,找到p的中序遍历次序下的直接后继s,并且r是s的父结点 if (p->lChild && p->rChild) { s = p->rChild; r = p; while (s->lChild != NULL) { r = s; s = s->lChild; } p->elemet = s->elemet; //将s的元素值复制到p p = s; //复制完元素之后,现在p指向新的真正需要delete掉的结点s q = r; //q指向p的父结点 } //通过上面那个if,此时p最多只有一棵非空子树 if (p->lChild) { c = p->lChild; } else if (p->rChild) { c = p->rChild; } //经过上面的判断,此时p还是根结点,说明该根结点最多只有一棵非空子树,且已经被c标识 if (p == root) { root = c; //让c成为新根 } else if (p == q->lChild) { q->lChild = c; //让c替代p成为q的左孩子 } else { q->rChild = c; //让c替代p成为q的右孩子 } //通过上面所有操作,此时p一定是最后需要被delete的结点 delete (p); return true; }
测试用例:
int main() { BSTree<int> bsTree; int n = 9; int nums = {28, 21, 36, 25, 33, 43, 23, 35, 34}; for (int i = 0; i < n; ++i) { bsTree.Insert(nums[i]); } cout<<"先序遍历:"; bsTree.PreOrder(Visit); cout<<endl; cout<<"中序遍历:"; bsTree.InOrder(Visit); cout<<endl; cout<<"后序遍历:"; bsTree.PostOrder(Visit); cout<<endl; cout<<"层次遍历:"; bsTree.LayerOrder(Visit); cout<<endl; cout<<"测试search成员函数......."<<endl; int searchT = 33; if (bsTree.Search(searchT)) { cout<<searchT<<" exists."<<endl; } else { cout<<searchT<<" doesn't exist."<<endl; } int removeNums[3] = {23, 21, 28}; for (int i = 0; i < 3; ++i) { bsTree.Remove(removeNums[i]); cout << "删除"<<removeNums[i]<<"之后......." << endl; cout << "先序遍历:"; bsTree.PreOrder(Visit); cout << endl; cout << "中序遍历:"; bsTree.InOrder(Visit); cout << endl; cout << "后序遍历:"; bsTree.PostOrder(Visit); cout << endl; cout << "层次遍历:"; bsTree.LayerOrder(Visit); cout << endl; } return 0; }
为了便于观察,画出树的图形如下。
运行结果如下:
先序遍历:28 21 25 23 36 33 35 34 43 中序遍历:21 23 25 28 33 34 35 36 43 后序遍历:23 25 21 34 35 33 43 36 28 层次遍历:28 21 36 25 33 43 23 35 34 测试search成员函数....... 33 exists. 删除23之后....... 先序遍历:28 21 25 36 33 35 34 43 中序遍历:21 25 28 33 34 35 36 43 后序遍历:25 21 34 35 33 43 36 28 层次遍历:28 21 36 25 33 43 35 34 删除21之后....... 先序遍历:28 25 36 33 35 34 43 中序遍历:25 28 33 34 35 36 43 后序遍历:25 34 35 33 43 36 28 层次遍历:28 25 36 33 43 35 34 删除28之后....... 先序遍历:33 25 36 35 34 43 中序遍历:25 33 34 35 36 43 后序遍历:25 34 35 43 36 33 层次遍历:33 25 36 35 43 34 Process finished with exit code 0
相关文章推荐
- 数据结构-二叉树(应用篇)-之二叉搜索树 C和C++的实现
- 数据结构-二叉搜索树(Binary Search Tree)的C++实现模板
- 数据结构——树(9)——二叉搜索树的操作实现C++代码
- 数据结构_树_赫夫曼树及赫夫曼编码_C++实现
- 数据结构_链表_稀疏多项式求值_C++实现
- 一个二叉搜索树的C++实现
- 数据结构C++模板实现之----------------单向链表
- 数据结构:矩阵程序C++实现
- 数据结构各种算法实现C++
- 数据结构C++实现---栈
- 二叉搜索树 -【动态规划】最优C++实现
- 数据结构_串_串的一些操作_C++实现
- 如何用c++实现四叉数的数据结构(一)
- 数据结构_串_串的模式匹配_KMP算法_C++实现
- 数据结构_串_用链表做存储结构实现KMP算法_C++实现
- 数据结构_链表_多项式求导_C++实现
- 数据结构 链表的lua实现 仿照C++中list 实现
- 二叉搜索树C++实现
- 数据结构学习系列二-链表的C++实现
- 算法与数据结构课程中的c++实现的顺序表和链表