树的先序 中序 后序 非递归算法

本文详细介绍了非递归算法在二叉树遍历中的应用,通过将空间消耗从栈区转换到堆区,有效避免了栈溢出导致的程序崩溃问题。文章提供了具体的代码实现,包括前序、中序和后序遍历的非递归算法,并使用C++的stack容器来辅助实现。

非递归算法将空间消耗从栈区转换到堆区,避免了栈溢出的导致程序崩溃。

typedef struct trnode
{
    char x;
    struct trnode* lchild, * rchild;
} Trnode, *Tree;

Tree buildtree(char * &s)
{
    if(*s && *s != ',')
    {
        Tree tr = (Tree) malloc( sizeof(Trnode) );
        tr->x = *s;
        tr->lchild = buildtree(++s);
        tr->rchild = buildtree(++s);
        return tr;
    }
    return NULL;
}

void inorder(Tree rt) //中序
{
    stack<Tree> S;
    S.push(rt);
    Tree p = rt;
    while(!S.empty())
    {
        while(p)
        {
            p=p->lchild;
            S.push(p);
        }
        S.pop();
        if(S.empty()) break;
        p = S.top();
        S.pop();
        cout<<p->x;
        p = p->rchild;
        S.push(p);
    }
    cout<<endl;
}

void preorder(Tree rt) //先序
{
    stack<Tree> S;
    S.push(rt);
    Tree p = rt;
    while(!S.empty())
    {
        while(p)
        {
            cout<<p->x;
            p=p->lchild;
            S.push(p);
        }
        S.pop();
        if(S.empty()) break;
        p = S.top();
        S.pop();
        p = p->rchild;
        S.push(p);
    }
    cout<<endl;
}

void postorder(Tree rt)  //后序
{

    stack<Tree> S;
    stack<Tree> ans;
    S.push(rt);
    Tree p = rt;
    while(!S.empty())
    {
        while(p)
        {
            ans.push(p);
            p=p->rchild;
            S.push(p);
        }
        S.pop();
        if(S.empty()) break;
        p = S.top();
        S.pop();
        p = p->lchild;
        S.push(p);
    }
    while( !ans.empty() )
    {
        cout<<ans.top()->x;
        ans.pop();
    }
    cout<<endl;
}
1.遍历非递归算法#define maxsize 100typedef struct{ Bitree Elem[maxsize]; int top;}SqStack;void PreOrderUnrec(Bitree t){ SqStack s; StackInit(s); p=t; while (p!=null || !StackEmpty(s)) { while (p!=null) //遍历左子 { visite(p->data); push(s,p); p=p->lchild; }//endwhile if (!StackEmpty(s)) //通过下一次循环中的内嵌while实现右子遍历 { p=pop(s); p=p->rchild; }//endif }//endwhile }//PreOrderUnrec2.中遍历非递归算法#define maxsize 100typedef struct{ Bitree Elem[maxsize]; int top;}SqStack;void InOrderUnrec(Bitree t){ SqStack s; StackInit(s); p=t; while (p!=null || !StackEmpty(s)) { while (p!=null) //遍历左子 { push(s,p); p=p->lchild; }//endwhile if (!StackEmpty(s)) { p=pop(s); visite(p->data); //访问根结点 p=p->rchild; //通过下一次循环实现右子遍历 }//endif }//endwhile}//InOrderUnrec3.后序遍历非递归算法#define maxsize 100typedef enum{L,R} tagtype;typedef struct { Bitree ptr; tagtype tag;}stacknode;typedef struct{ stacknode Elem[maxsize]; int top;}SqStack;void PostOrderUnrec(Bitree t){ SqStack s; stacknode x; StackInit(s); p=t; do { while (p!=null) //遍历左子 { x.ptr = p; x.tag = L; //标记为左子 push(s,x); p=p->lchild; } while (!StackEmpty(s) && s.Elem[s.top].tag==R) { x = pop(s); p = x.ptr; visite(p->data); //tag为R,表示右子访问完毕,故访问根结点 } if (!StackEmpty(s)) { s.Elem[s.top].tag =R; //遍历右子 p=s.Elem[s.top].ptr->rchild; } }while (!StackEmpty(s));}//PostOrderUnrec
### 二叉、中后序遍历算法 #### 遍历 遍历是一种深度优遍历方法,其顺为:访问根节点 -> 遍历左子 -> 遍历右子。以下是递归和非递归实现: **递归实现** ```python def preorder_recursive(root, result=[]): if root is None: return [] result.append(root.val) # 访问当前节点 preorder_recursive(root.left, result) # 遍历左子 preorder_recursive(root.right, result) # 遍历右子 return result ``` **非递归实现** 非递归实现需借助栈完成操作。 ```python def preorder_iterative(root): if not root: return [] stack, result = [root], [] # 初始化栈并压入根节点 while stack: node = stack.pop() # 弹出栈顶元素 result.append(node.val) # 处理当前节点 if node.right: # 右子进栈(因为栈是后进出) stack.append(node.right) if node.left: # 左子后进栈 stack.append(node.left) return result ``` 以上两种方法均实现了遍历[^1][^2]。 --- #### 中遍历 中遍历也是一种深度优遍历方法,其顺为:遍历左子 -> 访问根节点 -> 遍历右子**递归实现** ```python def inorder_recursive(root, result=[]): if root is None: return [] inorder_recursive(root.left, result) # 遍历左子 result.append(root.val) # 访问当前节点 inorder_recursive(root.right, result) # 遍历右子 return result ``` **非递归实现** 同样利用栈模拟递归过程。 ```python def inorder_iterative(root): if not root: return [] stack, result = [], [] # 初始化空栈 current = root while stack or current: if current: # 将左子全部压入栈 stack.append(current) current = current.left else: current = stack.pop() result.append(current.val) # 访问当前节点 current = current.right # 转向右子 return result ``` 上述代码展示了如何通过迭代方式完成中遍历[^3]。 --- #### 后序遍历 后序遍历的顺为:遍历左子 -> 遍历右子 -> 访问根节点。 **递归实现** ```python def postorder_recursive(root, result=[]): if root is None: return [] postorder_recursive(root.left, result) # 遍历左子 postorder_recursive(root.right, result) # 遍历右子 result.append(root.val) # 访问当前节点 return result ``` **非递归实现** 由于后序遍历需要处理左右子再处理根节点,因此可以通过两次反转辅助栈的方式实现。 ```python def postorder_iterative(root): if not root: return [] stack, output = [root], [] # 初始栈仅含根节点 while stack: node = stack.pop() # 弹出栈顶元素 output.insert(0, node.val) # 插入到输出列表头部 if node.left: stack.append(node.left) # 左子入栈 if node.right: stack.append(node.right) # 右子后入栈 return output ``` 此方法通过调整弹出顺完成了后序遍历[^4]。 --- ### 总结 三种遍历的核心区别在于访问根节点的时间点不同。无论是递归还是非递归实现,都遵循一定的逻辑框架,并可通过适当的数据结构优化性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值