树的三种DFS策略(前序、中序、后序)遍历

之前刷leetcode的时候,知道求排列组合都需要深度优先搜索(DFS), 那么前序、中序、后序遍历是什么鬼,一直傻傻的分不清楚。直到后来才知道,原来它们只是DFS的三种不同策略。

N = Node(节点)

L = Left(左节点)

R = Right(右节点)

在深度优先搜索的时候,以Node的访问顺序,定义了三种不同的搜索策略:

前序遍历:结点 —> 左子树 —> 右子树

中序遍历:左子树—> 结点 —> 右子树

后序遍历:左子树 —> 右子树 —> 结点

##前序遍历

Pre-order: F, B, A, D, C, E, G, I, H.

##中序遍历

In-order: A, B, C, D, E, F, G, H, I.

在二叉搜索树(BST)中,中序遍历返回递增的一个序列

##后序遍历

Post-order: A, C, E, D, B, H, I, G, F.

##递归代码

递归实现比较直观容易,通常DFS遍历,都需要传递一个参数 or 设置一个全局变量,来保存结果

def pre_order(self, node, results):
    if node is None:
        return
    results.append(node.val)
    self.pre_order(node.left, results)
    self.pre_order(node.right, results)
def in_order(self, node, results):
    if node is None:
        return
    self.in_order(node.left, results)
    results.append(node.val)
    self.in_order(node.right, results)
def post_order(self, node, results):
    if node is None:
        return
    self.post_order(node.left, results)
    self.post_order(node.right, results)
    results.append(node. 大专栏  树的三种DFS策略(前序、中序、后序)遍历val)

##非递归代码

深度优先遍历的非递归代码,一定用到的是stack数据接口

非递归实现前序和中序还可以,后续遍历就非常烧脑了

前序最简单,相当于for循环所有children,所以一版非递归DFS,就用前序就好了。

中序遍历,由于对于BST有一个递增的特性,所以还是比较常用的

def preorderTraversal(self, root):
    results = []
    if root is None:
        return results
    stack = [root]
    while(len(stack) > 0):
        node = stack.pop()
        results.append(node.val)
        # right first so left pop fisrt
        if node.right is not None:
            stack.append(node.right)
        if node.left is not None:
            stack.append(node.left)
    return results
def inorderTraversal(self, root):
    results = []
    if root is None:
        return results
    stack = []
    node = root
    while(len(stack) > 0 or node is not None):
        if (node is not None):
            stack.append(node)
            node = node.left
        else:
            node = stack.pop()
            results.append(node.val)
            node = node.right
    return results
def postorderTraversal(self, root):
    results = []
    if root is None:
        return results
    node = root
    stack = []
    lastNodeVisted = None
    while(len(stack) > 0 or node is not None):
        if node is not None:
            stack.append(node)
            node = node.left
        else:
            peek = stack[-1] # last element
            if (peek.right is not None and lastNodeVisted != peek.right):
                node = peek.right
            else:
                results.append(peek.val)
                lastNodeVisted = stack.pop()
    return results

–END–

原文地址:https://www.cnblogs.com/lijianming180/p/12239836.html

时间: 2024-11-08 21:41:28

树的三种DFS策略(前序、中序、后序)遍历的相关文章

树的前序 中序 后序遍历

1.后序遍历,每次递归的时候最后一个节点一定是该层的根节点 2.中序遍历,根节点的左边是左子树,右边是右子树 二叉树的遍历 遍历即将树的所有结点访问且仅访问一次.按照根节点位置的不同分为前序遍历,中序遍历,后序遍历. 前序遍历:根节点->左子树->右子树 中序遍历:左子树->根节点->右子树 后序遍历:左子树->右子树->根节点 例如:求下面树的三种遍历 前序遍历:abdefgc 中序遍历:debgfac 后序遍历:edgfbca

使用三种方式定位html中的元素

1)使用三种方式定位html中的元素a)通过ID$("#ID")b)通过标签名$("标签名")c)通过样式名$(".样式名")2)dom中,需要判段查找到的元素是否为null,而jquery中,无需判段,因为jquery本身内置判段器,在查找不到的情况下,返回"undefined" <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN&quo

二叉树知道前序中序或者中序后序求另外一个排列

二叉树的遍历: 前序遍历:根节点->左子树->右子树 中序遍历:左子树->根节点->右子树 后序遍历:左子树->右子树->根节点 求下面树的三种遍历: 前序遍历:abdefgc 中序遍历:debgfac 后序遍历:edgfbca 详细的二叉树的操作可以看一下我之前写的文章 二叉树java 已知前序.中序遍历,求后序遍历 前序遍历的第一个值就是根节点,然后再中序遍历中找到这个值,那么这个值的左边部分即为当前二叉树的左子树部分前序遍历结果,这个值的右边部分即为当前二叉树的右

算法进阶面试题03——构造数组的MaxTree、最大子矩阵的大小、2017京东环形烽火台问题、介绍Morris遍历并实现前序/中序/后序

接着第二课的内容和带点第三课的内容. (回顾)准备一个栈,从大到小排列,具体参考上一课.... 构造数组的MaxTree [题目] 定义二叉树如下: public class Node{ public int value; public Node left; public Node right; public Node(int data){ this.value=data; } } 一个数组的MaxTree定义如下: ◆ 数组必须没有重复元素 ◆ MaxTree是一颗二叉树,数组的每一个值对应一

经典白话算法之二叉树中序前序序列(或后序)求解树

这种题一般有二种形式,共同点是都已知中序序列.如果没有中序序列,是无法唯一确定一棵树的. <1>已知二叉树的前序序列和中序序列,求解树. 1.确定树的根节点.树根是当前树中所有元素在前序遍历中最先出现的元素. 2.求解树的子树.找出根节点在中序遍历中的位置,根左边的所有元素就是左子树,根右边的所有元素就是右子树.若根节点左边或右边为空,则该方向子树为空:若根节点 边和右边都为空,则根节点已经为叶子节点. 3.递归求解树.将左子树和右子树分别看成一棵二叉树,重复1.2.3步,直到所有的节点完成定

算法实验-二叉树的创建和前序-中序-后序-层次 遍历

对于二叉树的创建我是利用先序遍历的序列进行创建 能够对于树节点的内容我定义为char型变量 '0'为空,即此处的节点不存在 头文件 Tree.h //链式二叉树的头文件 #pragma once #include<iostream> #include<queue> using namespace std; class BinaryTreeNode { public: char data; BinaryTreeNode *leftChild,*rightChild; BinaryTr

二叉树的前序中序后序遍历相互求法

二叉树的前中后序遍历,他们的递归非递归.还有广度遍历,参见二叉树的前中后序遍历迭代&广度遍历和二叉树的前中后序遍历简单的递归 现在记录已知二叉树的前序中序后序遍历的两个,求另外一个.一般,这两个中一定有中序遍历. 1.已知前序和中序,求后序遍历: 前序:ABDECFG  中序:DBEAFCG 思路简单:前序的第一个节点就是根节点, 中序中找到根节点的位置,根节点之前是其左子树,之后是右子树   按此顺序,依次在左子树部分遍历,右子树部分遍历 C++ 代码: TreeNode *BinaryTre

已知二叉树前、中序遍历,求后序 / 已知二叉树中、后序遍历,求前序

void solve(int start,int end,int root) { // 前序和中序 -> 后序 // 每次调用solve()函数,传入pre-order的start,end,root if (start > end) // 递归边界 return; int i = start; while (i < end && in.at(i) != pre.at(root)) // 找到左右子树的分割点 i++; solve(start, i - 1, root +

前序中序后序遍历非递归实现

#include<iostream> #include<vector> #include<stack> #include<string> #include<algorithm> #include<numeric> using namespace std; class node{ public: int val; node* left; node* right; node():val(0),left(NULL),right(NULL){