利用后序遍历非递归的思想,结合栈。
如果某结点的左右子树均未找到指定结点,则将该结点出栈,那就需要标记一下当前结点的访问状态。
直到找到结点,或者遍历完树仍未找到(此时栈空)。
typedef struct BNode
{
int data;
BNode *lchild,*rchild;
}*BTree;
typedef struct
{
BNode* bt;
int isFirst;
}SElemType;
typedef struct
{
SElemType leaf[MAXSIZE];
int top;
} Stack;
void initStack(Stack &s)
{
s.top=0;
}
void push(Stack &s,SElemType n)
{
s.leaf[s.top]=n;
s.top++;
}
SElemType pop(Stack &s) //出栈并返回栈顶元素
{
SElemType x=s.leaf[s.top-1];
s.top--;
return x;
}
int isEmpty(Stack s)
{
if(s.top==0) return 1; //空
return 0; //非空
}
void createBTree(BTree &t)
{
int ch;
cin>>ch;
if(ch==0)
t=NULL;
else
{
t=(BTree)malloc(sizeof(BNode));
t->data=ch;
createBTree(t->lchild);
createBTree(t->rchild);
}
}
Stack getPath(BTree t,int x)
{
Stack s;
initStack(s);
SElemType elem;
while(t||!isEmpty(s))
{
//所有左孩子入栈
while(t)
{
elem.isFirst=1; //第一次访问
elem.bt=t;
push(s,elem);
if(t->data==x) return s; //找到指定结点,返回。
t=t->lchild;
}
if(!isEmpty(s))
{
elem=pop(s);
t=elem.bt->rchild;
//如果第一次访问该节点(即还有右子树没有查找),出栈后取其右孩子后,更改访问状态再放回
if(elem.isFirst==1)
{
elem.isFirst=0;
push(s,elem);
}
}
}
return s;
}
int main()
{
BTree t;
Stack sta;
int x;
cout<<"先序遍历输入树:";
createBTree(t);
cout<<"输入要查找的结点数据";
cin>>x;
sta=getPath(t,x);
cout<<"路径为:";
if(isEmpty(sta))
cout<<"不存在"<<endl;
else
{
while(!isEmpty(sta))
{
cout<<pop(sta).bt->data<<" ";
}
}
return 0;
}