用二叉链表实现二叉查找树(二)

来源:互联网 发布:移动端关键词优化软件 编辑:程序博客网 时间:2024/05/17 22:01
</pre><pre code_snippet_id="367806" snippet_file_name="blog_20140528_2_6875764" name="code" class="cpp">/*二叉查找树的链表实现:以及三种遍历方式,删除节点;查找节点;author:天下无双Date:2014-5-28Version:3.0*/#include <iostream>#include <string>typedef int T;//树内节点的数据类型using namespace std;class BiTree{private:struct BiNode{T data;BiNode *lchild,*rchild;BiNode(T d){data=d;lchild=nullptr;rchild=nullptr;}};BiNode *root;public:BiTree(){//root=root->rchild=root->rchild=nullptr;root=nullptr;}~BiTree(){}//使用递归创建二叉树//以二叉排序树的规则建立//指针的引用写法(推荐使用)bool addBiNode(BiNode *&nodeRoot,T d){if(nodeRoot==nullptr){BiNode *p=new BiNode(d);nodeRoot=p;cout<<p->data<<"  insert success!"<<endl;return true;}else if(nodeRoot!=nullptr&&d<nodeRoot->data){//往左子树递归addBiNode(nodeRoot->lchild,d);}else if(nodeRoot!=nullptr&&d>(nodeRoot)->data){//往右子树递归addBiNode(nodeRoot->rchild,d);}else{cout<<"树中已有该数据"<<endl;return false;}}BiNode *&getRoot(){//返回根指针的引用return root;}BiNode *getPtrToRoot()const{return root;}bool Traverse(const BiNode *b,string type)const{if(type=="PreOrderTraverse"){cout<<"\n先序遍历的结果为:"<<endl;PreOrderTraverse(b);return true;}else if(type=="InOrderTraverse"){cout<<"\n中序遍历的结果为:"<<endl;InOrderTraverse(b);return true;}else if(type=="PostOrderTraverse"){cout<<"\n后序遍历的结果为:"<<endl;PostOrderTraverse(b);return true;}else{cout<<"遍历类型无效!"<<endl;return false;}}//查找二叉树中是否存在该值bool Search(BiNode *&nodeRoot,T d){if(nodeRoot==nullptr)return false;else{if(nodeRoot->data==d){return true;}else if(nodeRoot->data<d){return  Search(nodeRoot->rchild,d);}elsereturn  Search(nodeRoot->lchild,d);}}//递归查找确定该节点所在位置bool DeleteBST(BiNode *&nodeRoot,T d){if(nullptr==nodeRoot)//当该节点为空return false;else{if(nodeRoot->data==d){//return Delete(nodeRoot);//Delete(nodeRoot);}else if(nodeRoot->data<d){return DeleteBST(nodeRoot->rchild,d);//DeleteBST(nodeRoot->rchild,d);}elsereturn DeleteBST(nodeRoot->lchild,d);//DeleteBST(nodeRoot->lchild,d);}}protected://删除操作//删除相应节点//如果该节点是叶子节点,即该节点左右孩子均为空,则只需将父节点指向该节点//指针置空即可//如果仅有左孩子或者仅有右孩子,则将对应节点上移//nodeRoot为要删除的节点//若既有左孩子,又有右孩子,看下面的注释bool Delete(BiNode *&nodeRoot){//如果要删除的节点右子树为空,则只需移动左子树if(nullptr==nodeRoot->rchild){BiNode *temp=nodeRoot;nodeRoot=nodeRoot->lchild;delete temp;return true;}else if(nullptr==nodeRoot->lchild){//若左子树空则移动右子树BiNode *temp=nodeRoot;nodeRoot=nodeRoot->rchild;delete temp;return true;}else{//左右子树均非空//将该节点的左子树的最右边的右节点数据和该节点互换//或者是将该节点右子树最左端的左节点和该节点数据互换//我这里是选择左子树的最右节点BiNode *temp=nodeRoot->lchild;//temp为该节点左子树的根节点BiNode *preTemp=nodeRoot->lchild;while(nullptr!=temp->rchild){preTemp=temp;//令preTemp指向最右节点的前驱temp=temp->rchild;//一直寻找最右的右节点//temp指向待删除的节点}//这时候temp指向最右的一个节点nodeRoot->data=temp->data;//交换数据,由于二叉查找树的特性,交换后依旧保持该特性。/*503070 20倘若删除的是50,则preTemp=temp=&30*/if(temp!=preTemp)preTemp->rchild=temp->lchild;//令前驱节点的右孩子变成被删除节点的左孩子elsenodeRoot->lchild=temp->lchild;delete temp;//删除右节点return true;}return false;}//T如果是结构或者类类型,需重载<<运算符void Visit(const BiNode *r)const{cout<<r->data<<" ";}//利用递归遍历,三种遍历原理都是一样的//前序遍历,先根遍历void PreOrderTraverse(const BiNode *nodeRoot)const{if(nodeRoot!=nullptr)Visit(nodeRoot);if(nodeRoot->lchild!=nullptr)PreOrderTraverse(nodeRoot->lchild);if(nodeRoot->rchild!=nullptr)PreOrderTraverse(nodeRoot->rchild);}//中根遍历void InOrderTraverse(const BiNode *nodeRoot)const{if(nodeRoot->lchild!=nullptr)InOrderTraverse(nodeRoot->lchild);if(nodeRoot!=nullptr)//当该点左子树空时Visit(nodeRoot);if(nodeRoot->rchild!=nullptr)InOrderTraverse(nodeRoot->rchild);}//后序遍历void PostOrderTraverse(const BiNode *nodeRoot)const{if(nodeRoot->lchild!=nullptr)PostOrderTraverse(nodeRoot->lchild);if(nodeRoot->rchild!=nullptr)PostOrderTraverse(nodeRoot->rchild);if(nodeRoot!=nullptr)Visit(nodeRoot);}};
感觉对于递归中的return还是有点不太清晰。
什么时候该用,什么时候不该用也不太清晰。
测试代码
<pre name="code" class="cpp">#include "bit4.cpp"int main(){BiTree b;//b.addBiNode(&b.root,50);//设立根节点值//二级指针写法b.addBiNode(b.getRoot(),50);//指针的引用写法int i;int arr[9]={30,40,35,27,100,90,110,95,-999};for(int j=0;j<9;j++){i=arr[j];if(i==-999)break;b.addBiNode(b.getRoot(),i);}b.Traverse(b.getPtrToRoot(),"PreOrderTraverse");b.Traverse(b.getPtrToRoot(),"InOrderTraverse");b.Traverse(b.getPtrToRoot(),"PostOrderTraverse");while(true){int k;cout<<"\n输入要查找的值:"<<endl;cin>>k;if(b.Search(b.getRoot(),k))cout<<"OK"<<endl;elsecout<<"NO"<<endl;}cin.get();system("pause");return 0;}






1 0
原创粉丝点击