/* _递归的精髓在二叉树的各种问题上体现的淋漓尽致!!! */ #include<stdio.h> #include<iostream> #include <stack> #include<vector> #include <assert.h> using namespace std; typedef struct node //二叉树结点的结构体表示形式 { int data; node *left,*right; }BTree; //---------------------------------_创建二叉树(前序方式)--------------------------- BTree *Create() { int data; scanf("%d",&data); if(data==0) return 0; //_输入0表示没有子节点 BTree *root=new BTree; root->data=data; root->left=Create(); root->right=Create(); return root; } BTree *Create2(int *x,int N) { static int i=-1; i++; if(x[i]==0) return 0; BTree *tmp=new BTree; tmp->data=x[i]; tmp->left=Create2(x,N); tmp->right=Create2(x,N); return tmp; } //-------------_遍历二叉树(前序方式)------------- void Preorder(BTree *tree) { if(tree==0) return; printf("%d ",tree->data); Preorder(tree->left); Preorder(tree->right); } void Preorder2(BTree *tree) //堆栈方式 { if(tree==0) return; stack <BTree*> s; s.push(tree); BTree *temp=0; while(!s.empty()) { temp=s.top(); printf("%d ",temp->data); s.pop(); if(temp->right) s.push(temp->right); if(temp->left) s.push(temp->left); } } //-------------_遍历二叉树(中序方式)------------- void Inorder(BTree *tree) { if(tree==0) return; Inorder(tree->left); printf("%d ",tree->data); Inorder(tree->right); } void Inorder2(BTree *tree) { if(tree==0) return; stack<BTree *> s; BTree *temp=0; s.push(tree); while(!s.empty()) { temp=s.top();s.pop(); //_弹出节点 while(temp) //_至最左端 { s.push(temp); temp=temp->left; } if(!s.empty()) { temp=s.top();s.pop(); //_取出最左端节点 printf("%d ",temp->data); s.push(temp->right); //_存入最左端节点的右兄弟,必须要压入右边的,无论有无节点 } } } //-------------_遍历二叉树(后序方式)------------- void Posorder(BTree *tree) { if(tree==0) {return;} Posorder(tree->left); Posorder(tree->right); printf("%d ",tree->data); } void Posorder2(BTree *tree) { if(!tree) return; stack<BTree *> s; BTree *temp=0,*lastvisit=0; s.push(tree); while(!s.empty()) { temp=s.top(); s.pop(); while(temp) { s.push(temp); temp=temp->left; } temp=s.top(); if(temp->right&&(temp->right!=lastvisit)) { s.push(temp->right); } else { lastvisit=temp; printf("%d ",lastvisit->data); s.pop(); } } } //-------------------------------------_二叉树的镜像-------------------------------- void GetImage(BTree *tree) //_求二叉树镜像 { if(tree==0) return; GetImage(tree->left); GetImage(tree->right); //互换left_和right BTree *tmp=tree->left;tree->left =tree->right;tree->right=tmp; } bool IsImage(BTree *tree1,BTree *tree2) //_判断二叉树是否是镜像的 { if(tree1==0&&tree2==0) return true; if(!tree1||!tree2) return false; if(tree1->data!=tree2->data) return false; bool same1=IsImage(tree1->left,tree2->right); bool same2=IsImage(tree1->right,tree2->left); return same1&&same2; } //--------------------------------------_与路径相关的问题--------------------------- BTree * findnode(BTree *tree ,int key) //_寻找key为某个值的节点,没找到返回0 { if(!tree) return 0; if(tree->data==key) return tree; BTree *tmp=findnode(tree->left,key); if(tmp) return tmp; tmp=findnode(tree->right,key); if(tmp) return tmp; return 0; } bool findnode1(BTree *tree,int key,BTree *&node) //_这种写法更简洁明白 { if(!tree) return false; if(tree->data==key) { node=tree;return true; } return findnode1(tree->left,key,node)||findnode1(tree->right,key,node); } bool findpath(BTree *tree,BTree *p,stack<BTree*> &st) //_从根节点到某一节点的路径 { if(!tree||!p) return 0; if(tree==p) { st.push(tree); return 1; } if(findpath(tree->left,p,st)||findpath(tree->right,p,st)) { //_以tree为根的左右子树中包含想要的节点,则根节点必在路径上 st.push(tree); return 1; } else return 0; } void findsumpath(BTree *tree,int expectedSum,int ¤tSum,vector<BTree *> &v) //_输出和为某一值的路径 { if(!tree) return; v.push_back(tree); currentSum+=tree->data; if(expectedSum==currentSum) { //_打印输出 vector<BTree *>::iterator it=v.begin(); while(it!=v.end()) { cout<<(*it)->data<<‘ ‘;it++;} cout<<endl; } if(tree->left) findsumpath(tree->left,expectedSum,currentSum,v); if(tree->right) findsumpath(tree->right,expectedSum,currentSum,v); //_每一次返回到父节点时,删除当前节点 currentSum-=v.back()->data; v.pop_back(); } BTree *LowestCommonAncestor(BTree *tree,BTree *A,BTree *B) //_最近公共父节点 {/*很简单:对于节点i,如果A和B分别在该节点的左右子树中,该节点就是了, 或者这个节点就是已知的两个节点中的一个,而另一个恰好在它的下面_ */ if(!tree) return 0; if(tree==A) return A; //_找到节点,返回 if(tree==B) return B; BTree *tmp1 = LowestCommonAncestor(tree->left,A,B); BTree *tmp2 = LowestCommonAncestor(tree->right,A,B); if(tmp1&&tmp2) return tree; //_左右都找到,父节点就是tree了 if(tmp1) return tmp1; if(tmp2) return tmp2; } //最近公共父节点的另一种方法:保存两条路径,_找最后一个相同的节点 //--------------------------------------_与二叉树自身相关的信息--------------------------- //深度(或高度)从1开始计算,有个好处是,当树为空时深度为0 int depth(BTree *tree) //_二叉树深度 { if(tree==0) return 0; return 1+max(depth(tree->left),depth(tree->right)); } void levelnum(BTree *tree,int depth,int current) //_输出某一层的节点 { if(tree==0) return; if(current==depth) { cout<<tree->data<<‘ ‘; return; } levelnum(tree->left, depth,current+1); levelnum(tree->right,depth,current+1); } //================================================================================= void main5() { //BTree *tree=Create(); int x[15]={1,2,4,0,0,5,7,0,0,0,3,0,6,0,0}; /* 1 ╱ ╲ 2 3 ╱ ╲ ╲ 4 5 6 ╱ 7 */ BTree *tree=Create2(x,15); //printf("前序遍历:");Preorder(tree);printf("\n"); //GetImage(tree); //printf("前序遍历:");Preorder(tree);printf("\n"); //printf("中序遍历:");Inorder2(tree);printf("\n"); //printf("后序遍历:");Posorder(tree);printf("\n"); /* 测试:从根节点到某一节点的路径 BTree *node;findnode1(tree,7,node); stack<BTree *> st; findpath(tree,node,st); while(!st.empty()) { cout<<st.top()->data<<" ";st.pop(); } ** 测试:和为某一值的路径 int currentSum=0;vector<BTree *> v; findsumpath(tree,10,currentSum,v); ** 测试:_最近公共父节点 BTree *A,*B,*C;findnode1(tree,4,A);findnode1(tree,2,B); C=LowestCommonAncestor(tree,A,B); cout<<C->data<<endl; ** 测试:_树的深度 cout<<depth(tree)<<endl; return; ** 测试:_输出树的某一层 levelnum(tree,4,1); */ }
时间: 2024-11-05 06:26:34