思想:用”栈”来消除递归。
主要是建立的过程,刚开始卡到了如果遇到’#’,那么在else中间出栈之后还需要读一个元素,这样在遇到连续的”#”之后,退栈并不能达到合适的位置,最后听了“巅峰”的建议,还是设置了flag,解决了问题,下面解释下建立过程的思想:
1:正常情况下以先序的方式输入串。一个一个字符读取;如果第一个字符不为“#”,先将它入栈,即我们的根。
2:初始化flag = 0,如果没有读到“#”,就开辟节点,获取栈顶元素,将字符存入栈顶元素的lchild,并且将它入栈。
3:要是读到”#”,就将flag = 1;重新读取一个元素,若不为“#”,就将它存入栈顶元素的rchild,然后将flag = 0;如果读到“#”后接下来又读到”#”,那么就出栈一个元素,并且判断当前栈顶的rchild是不是刚才出栈的元素。如果是刚才出栈的元素并且栈不为空,那就说明当前栈顶元素的左右子树都已经建立完毕,那就再出一个,再判断,直到不是才说明我们的将此时根的左边才完全建立好了,要是一直出到栈为空,那就说明完全建立完毕。
下面附上代码:
#include<stdio.h>
#include<stdlib.h>
#include "my_stack.h"
Tree creat(Head);
void PreOrder(Tree,Head);
void InOrder(Tree,Head);
void LastOrder(Tree,Head);
void LastOrder(Tree root,Head head)
{
Tree q = NULL;
while(root || head->top != -1 ) {
if(root) {
push(head,root);
root = root->lchild;
} //每次需要先走到最左边
else {
root = gettop(head);
if((root->rchild == NULL )|| (root->rchild == q)) { //取栈顶判断
//如果邮孩子为空或者右孩子刚被访问过,说明上一个元素的公恩两个已经结束了,那就访问根,
root = pop(head);
printf("%c ",root->data);
q = root; //这一步保存当前根的位置,以便下一次判断
root = NULL; //下一次直接判断
}
else {
root = root->rchild; //否则左边完毕就往右边走。
}
}
}
}
void InOrder(Tree root,Head head)
{
while(root || head->top != -1) {
if(root) {
push(head,root);
root = root->lchild;
}
else {
root = pop(head);
printf("%c ",root->data);
root = root->rchild;
}
}
}
void PreOrder(Tree root,Head head)
{
while(root || head->top != -1) {
if(root) {
printf("%c ",root->data);
push(head,root);
root = root->lchild;
}
else {
root = pop(head);
root = root->rchild;
}
}
}
Tree creat(Head head)
{
Tree p,q;
Tree root = NULL;
char ch;
int flag = 0;
ch = getchar();
if(ch == '#') {
return 0;
}
root = (Tree)malloc(sizeof(tree)); //为第一个节点申请空间并且入栈
p = root;
p->data = ch;
push(head,p);
while(head->top != -1 || ch != '#') {
ch = getchar();
if(ch == '#' && flag == 0) { //如果给右孩子填过值,那下面就走左边
flag = 1;
}
else if(ch == '#' && flag == 1) { //连续读到两个#,那就边判断边将右孩子和栈顶右孩子一样的出栈,
//说明右边这些部分已经结束
p = pop(head);
while(head->top != -1 && gettop(head)->rchild == p) {
p = pop(head);
}
}
else {
q = (Tree)malloc(sizeof(tree));
q->data = ch;
if(flag == 0) { //正常情况先访问左边
p = gettop(head);
push(head,q);
p->lchild = q;
}
if(flag == 1) { //要是读到'#'就来这一句。
p = gettop(head);
p->rchild = q;
push(head,q);
flag = 0;
}
}
}
return root;
}
int main(int argc,char *argv[])
{
Tree root = NULL;
Head head = initstack(head);
printf("非递归建树:\n");
root = creat(head);
printf("非递归先序遍历:\n");
PreOrder(root,head);
printf("\n");
printf("非递归中序遍历:\n");
InOrder(root,head);
printf("\n");
printf("非递归后序遍历:\n");
LastOrder(root,head);
printf("\n");
}