后序非递归遍历二叉树的应用
1.打印值为x的结点的所有祖先
栈从0开始,top初始值-1
#include "stdafx.h" #include<iostream> using namespace std; typedef struct BTreeNode { int data; struct BTreeNode *lchild,*rchild; }BTree; typedef struct stacknode { BTree *node; int tag;//tag为0表示结点左子女已经访问,为1表示右子女已经访问 }stack; int _tmain(int argc, _TCHAR* argv[]) { return 0; } void Search(BTree *b,int x) { stack s[100]; int top=-1; stack temp;//暂存结点信息 while(b||top>-1) { while(b) { temp.node=b; temp.tag=0;//左结点已访问 s[++top]=temp; b=b->lchild; } //以下为功能代码 if(b->data==x) { printf("所查结点的所有祖先为:\n"); for(int i=0;i<=top;i++) { cout<<s[i].node->data; } exit(0);//输出完成后退出程序 } while(top&&s[top].tag==1){ //表示右子树访问完毕,所以访问根节点 //b = s[top --].node; //cout << b->val << ' '; /*之前是写这两行,但是会导致最后top为0时,p非空,所以会不断循环最外层的while(p||top) 如果要写这两行而不写下面那句的话,要采用do{}while(top);*/ cout << s[top --].node->data<< ' '; } if(top!=-1) { s[top].tag= 1; //右结点已访问 b = s[top].node; b = b->rchild; } } }
2.p,q最近公共祖先
#include "stdafx.h" #include<iostream> using namespace std; typedef struct BTreeNode { int data; struct BTreeNode *lchild,*rchild; }BTree; typedef struct stacknode { BTree *node; int tag;//tag为0表示结点左子女已经访问,为1表示右子女已经访问 }stack; int _tmain(int argc, _TCHAR* argv[]) { return 0; } BTree *Ancestor(BTree *b,BTree *p,BTree *q,BTree *r) { stack s[100],s1[100];//辅助栈 int top=-1,top1=-1; stack temp;//暂存结点信息 while(b||top>-1) { while(b) { temp.node=b; temp.tag=0;//左结点已访问 s[++top]=temp; b=b->lchild; } //以下为功能代码 if(b==p)//不失一般性,设p在q的左边,所以p必定先于q被访问,把栈中已有元素复制到另一栈中去 { for(int i=0;i<=top;i++) { s1[i]=s[i]; } top1=top; } if(b==q)//找到q { for(int i=top;i>=0;i--)//将栈中元素的树结点到s1中去匹配 { BTree *pp=s[i].node; for(int j=top1;j>=0;j--) { if(s1[j].node==pp) return pp; } } } while(top&&s[top].tag==1){ //表示右子树访问完毕,所以访问根节点 //b = s[top --].node; //cout << b->val << ' '; /*之前是写这两行,但是会导致最后top为0时,p非空,所以会不断循环最外层的while(p||top) 如果要写这两行而不写下面那句的话,要采用do{}while(top);*/ cout << s[top --].node->data<< ' '; } if(top!=-1) { s[top].tag= 1; //右结点已访问 b = s[top].node; b = b->rchild; } } }
3.到叶结点的路径
#include "stdafx.h" #include<iostream> using namespace std; typedef struct BTreeNode { int data; struct BTreeNode *lchild,*rchild; }BTree; typedef struct stacknode { BTree *node; int tag;//tag为0表示结点左子女已经访问,为1表示右子女已经访问 }stack; int _tmain(int argc, _TCHAR* argv[]) { return 0; } BTree *Ancestor(BTree *b,BTree *p,BTree *q,BTree *r) { stack s[100],s1[100];//辅助栈 int top=-1,top1=-1; stack temp;//暂存结点信息 while(b||top>-1) { while(b) { temp.node=b; temp.tag=0;//左结点已访问 s[++top]=temp; b=b->lchild; } //以下为功能代码 if(b->lchild!=NULL&&b->rchild!=NULL) { for(int i=0;i<=top;i++) { cout<<s[i].node->data; } cout<<b->data; } while(top&&s[top].tag==1){ //表示右子树访问完毕,所以访问根节点 //b = s[top --].node; //cout << b->val << ' '; /*之前是写这两行,但是会导致最后top为0时,p非空,所以会不断循环最外层的while(p||top) 如果要写这两行而不写下面那句的话,要采用do{}while(top);*/ cout << s[top --].node->data<< ' '; } if(top!=-1) { s[top].tag= 1; //右结点已访问 b = s[top].node; b = b->rchild; } } }
4.根节点到叶结点最长路径
#include "stdafx.h" #include<iostream> using namespace std; typedef struct BTreeNode { int data; struct BTreeNode *lchild,*rchild; }BTree; typedef struct stacknode { BTree *node; int tag;//tag为0表示结点左子女已经访问,为1表示右子女已经访问 }stack; int _tmain(int argc, _TCHAR* argv[]) { return 0; } BTree *Ancestor(BTree *b,BTree *p,BTree *q,BTree *r) { stack s[100],l[100];//辅助栈 int top=-1,top1=-1,longest=0; stack temp;//暂存结点信息 while(b||top>-1) { while(b) { temp.node=b; temp.tag=0;//左结点已访问 s[++top]=temp; b=b->lchild; } //以下为功能代码 if(s[top].tag==1)//右结点已访问 { if(s[top].node->lchild&&s[top].node->rchild) { if(top>longest) { for(int i=0;i<=top;i++) { l[i]=s[i];//保存栈中结点 } longest=top; top--;//出栈 } } } while(top&&s[top].tag==1){ //表示右子树访问完毕,所以访问根节点 //b = s[top --].node; //cout << b->val << ' '; /*之前是写这两行,但是会导致最后top为0时,p非空,所以会不断循环最外层的while(p||top) 如果要写这两行而不写下面那句的话,要采用do{}while(top);*/ cout << s[top --].node->data<< ' '; } if(top!=-1) { s[top].tag= 1; //右结点已访问 b = s[top].node; b = b->rchild; } } }