非递归遍历二叉树

二叉树遍历

  • 递归型写法
  • 非递归型写法
  • 非递归型写法要点
  • 准备工作

递归型写法

非递归型写法与要点

先序遍历

  • 非递归的写法比递归写法要麻烦一点,要用到栈来存储树的结点,在理解非递归方法的时候要重点理解栈中保存的元素的共同点是什么,在前序访问中,栈中元素都是自己和自己的左孩子都访问过了,而右孩子还没有访问到的节点,如果不太懂可以看下面的详细步骤图解。

# PreOrderLoop(TreeNode *root)
class Solution(object):
    # void PreOrderLoop(TreeNode *root)
    # {
    #     std::stack<TreeNode *> s;
    # TreeNode *cur, *top;
    # cur = root;
    # while (cur != NULL || !s.empty())
    # {
    # while (cur != NULL)
    #     {
    #         printf("%c ", cur->data);
    #     s.push(cur);
    #     cur = cur->left;
    #     }
    #
    #     top = s.top();
    #     s.pop();
    #
    #     cur = top->right;
    # }
    # }
    def PreOrderLoop(self, root):
        s = stack()
        cur = root
        top = None
        rst = []
        while(cur != None or not s.empty()):
            while(cur != None):
                rst.append(cur.val)
                s.push(cur)
                cur = cur.left
            # top = s.pick()
            # s.pop()
            top = s.pop()
            cur = top.right
        return rst

    def self_testing(self):
        root = TreeNode(1)
        root.left = TreeNode(2)
        root.right = TreeNode(3)
        root.left.right = TreeNode(5)
        print self.PreOrderLoop(root=root)
        root = TreeNode(5)
        root.left = TreeNode(4)
        root.right = TreeNode(8)
        root.left.left = TreeNode(11)
        root.left.left.left = TreeNode(7)
        root.left.left.right = TreeNode(2)
        root.right.left = TreeNode(13)
        root.right.right = TreeNode(4)
        root.right.right.right = TreeNode(1)
        print self.PreOrderLoop(root=root)
# Solution().self_testing()

中序遍历

  • 中序访问的非递归写法和前序一样,都要用到一个栈来辅助存储,不一样的地方在于前序访问时,栈中保存的元素是右子树还没有被访问到的节点的地址,而中序访问时栈中保存的元素是节点自身和它的右子树都没有被访问到的节点地址。

class Solution(object):
    # # InOrderLoop(TreeNode *root)
    # void InOrderLoop(TreeNode *root)
    # {
    #     std::stack<TreeNode *> s;
    # TreeNode *cur;
    # cur = root;
    # while (cur != NULL || !s.empty())
    # {
    # while (cur != NULL)
    #     {
    #         s.push(cur);
    #     cur = cur->left;
    #     }
    #
    #     cur = s.top();
    #     s.pop();
    #     printf("%c ", cur->data);
    #
    #     cur = cur->right;
    # }
    # }
    def InOrderLoop(self, root):
        s = stack()
        cur = root
        rst = []
        while(cur != None or not s.empty()):
            while(cur != None):
                s.push(cur)
                cur = cur.left
            cur = s.pop()
            rst.append(cur.val)

            cur = cur.right
        return rst

    def self_testing(self):
        root = TreeNode(1)
        root.left = TreeNode(2)
        root.right = TreeNode(3)
        root.left.right = TreeNode(5)
        print self.InOrderLoop(root=root)
        root = TreeNode(5)
        root.left = TreeNode(4)
        root.right = TreeNode(8)
        root.left.left = TreeNode(11)
        root.left.left.left = TreeNode(7)
        root.left.left.right = TreeNode(2)
        root.right.left = TreeNode(13)
        root.right.right = TreeNode(4)
        root.right.right.right = TreeNode(1)
        print self.InOrderLoop(root=root)

Solution().self_testing()

后序遍历

  • 后序遍历的非递归同样要借助一个栈来保存元素,栈中保存的元素是它的右子树和自身都没有被遍历到的节点,与中序遍历不同的是先访问右子树,在回来的时候再输出根节点的值。需要多一个last指针指向上一次访问到的节点,用来确认是从根节点的左子树返回的还是从右子树返回的。

class Solution(object):
    # # PostOrderLoop
    # void PostOrderLoop(TreeNode *root)
    # {
    #     std::stack<TreeNode *> s;
    # TreeNode *cur, *top, *last = NULL;
    # cur = root;
    # while (cur != NULL || !s.empty())
    # {
    # while (cur != NULL)
    #     {
    #         s.push(cur);
    #     cur = cur->left;
    #     }
    #
    #     top = s.top();
    #
    #     if (top->right == NULL || top->right == last){
    #     s.pop();
    #     printf("%c ", top->data);
    #     last = top;
    #     }
    #     else {
    #     cur = top->right;
    #     }
    # }
    # }
    def PostOrderLoop(self, root):
        s = stack()
        cur = top = last = None
        cur = root
        rst = []
        while(cur != None or not s.empty()):
            while(cur != None):
                s.push(cur)
                cur = cur.left

            top = s.pick()
            if(top.right == None or top.right == last):
                s.pop()
                rst.append(top.val)
                last = top
            else:
                cur = top.right
        return rst
    def self_testing(self):
        root = TreeNode(1)
        root.left = TreeNode(2)
        root.right = TreeNode(3)
        root.left.right = TreeNode(5)
        print self.PostOrderLoop(root=root)
        root = TreeNode(5)
        root.left = TreeNode(4)
        root.right = TreeNode(8)
        root.left.left = TreeNode(11)
        root.left.left.left = TreeNode(7)
        root.left.left.right = TreeNode(2)
        root.right.left = TreeNode(13)
        root.right.right = TreeNode(4)
        root.right.right.right = TreeNode(1)
        print self.PostOrderLoop(root=root)

Solution().self_testing()

层序遍历

  • 层序遍历的思路是,创建一个队列,先将根节点(A)入队,然后用front指针将根节点记下来,再将根节点出队,接下来看front节点(也就是刚才的根节点)有没有左孩子或右孩子,如果有,先左(B)后右(C)入队,最后输出front节点的值,只要队列还不为空,就说明还没有遍历完,就进行下一次循环,这时的队头元素(front)则为刚才入队的左孩子(B),然后front出队,再把它的左右孩子拉进来(如果有),因为队列的先进先出性质,B的左右孩子DE是排在C后面的,然后输出B,下一次循环将会拉人C的左右孩子FG,最后因为FG没有左右孩子,一直出队,没有入队元素,队列迟早会变为空,当队列为空时,整颗树就层序遍历完成了,结束循环。

class Solution(object):
    # void LevelOrder(TreeNode *root)
    # {
    #     std::queue<TreeNode *> q;
    # TreeNode *front;
    #
    # if (root == NULL)return;
    #
    # q.push(root);
    #
    # while (!q.empty())
    # {
    #     front = q.front();
    # q.pop();
    #
    # if (front->left)
    # q.push(front->left);
    #
    # if (front->right)
    # q.push(front->right);
    #
    # printf("%c ", front->data);
    # }
    # }
    def LevelOrder(self, root):
        q = queue()
        front = None
        rst = []
        if(root == None): return rst
        q.push(root)
        while(not q.empty()):
            front = q.pop()
            if(front.left != None):
                q.push(front.left)
            if(front.right != None):
                q.push(front.right)
            rst.append(front.val)
        return rst

    def self_testing(self):
        root = TreeNode(1)
        root.left = TreeNode(2)
        root.right = TreeNode(3)
        root.left.right = TreeNode(5)
        print self.LevelOrder(root=root)
        root = TreeNode(5)
        root.left = TreeNode(4)
        root.right = TreeNode(8)
        root.left.left = TreeNode(11)
        root.left.left.left = TreeNode(7)
        root.left.left.right = TreeNode(2)
        root.right.left = TreeNode(13)
        root.right.right = TreeNode(4)
        root.right.right.right = TreeNode(1)
        print self.LevelOrder(root=root)

Solution().self_testing()

准备工作

  • 你需要了解下栈、队列相关知识,并且会用
  • python下可以使用deque,选型参考python/python-stack.md

完整代码


from collections import deque
class stack(deque):
    def push(self, x):
        self.append(x)

    def pick(self):
        return self[-1]

    def empty(self):
        return len(self) == 0

    def self_testing(self):

        s = stack()
        s.push(5);s.push(3);s.push(4);s.push(5)
        print s
        print s.pick()
        print s.pop()
        print s

class queue(deque):
    def push(self, x):
        self.append(x)

    def pick(self, idx = 0):
        return self[idx] if(len(self) > idx) else None

    def empty(self):
        return len(self) == 0

    def pop(self):
        return self.popleft()

    def get(self):
        tmp = self[0]
        self.remove(tmp)
        return tmp

    def self_testing(self):
        q = queue()
        q.push(5);q.push(3);q.push(4);q.push(5)
        # print q
        # print q.pick();print q.pick(2)
        # print q.get()

def initFullBinaryTree(source = []):
    if(len(source) < 0):
        return None
    q = queue(maxsize=len(source))
    node_sum = len(source) -1
    for i in source:
        q.put((i,0))
    # root =
    while(not q.empty()):
        pass



# PreOrderLoop(TreeNode *root)
class Solution(object):
    # void PreOrderLoop(TreeNode *root)
    # {
    #     std::stack<TreeNode *> s;
    # TreeNode *cur, *top;
    # cur = root;
    # while (cur != NULL || !s.empty())
    # {
    # while (cur != NULL)
    #     {
    #         printf("%c ", cur->data);
    #     s.push(cur);
    #     cur = cur->left;
    #     }
    #
    #     top = s.top();
    #     s.pop();
    #
    #     cur = top->right;
    # }
    # }
    def PreOrderLoop(self, root):
        s = stack()
        cur = root
        top = None
        rst = []
        while(cur != None or not s.empty()):
            while(cur != None):
                rst.append(cur.val)
                s.push(cur)
                cur = cur.left
            # top = s.pick()
            # s.pop()
            top = s.pop()
            cur = top.right
        return rst

    def self_testing(self):
        root = TreeNode(1)
        root.left = TreeNode(2)
        root.right = TreeNode(3)
        root.left.right = TreeNode(5)
        print self.PreOrderLoop(root=root)
        root = TreeNode(5)
        root.left = TreeNode(4)
        root.right = TreeNode(8)
        root.left.left = TreeNode(11)
        root.left.left.left = TreeNode(7)
        root.left.left.right = TreeNode(2)
        root.right.left = TreeNode(13)
        root.right.right = TreeNode(4)
        root.right.right.right = TreeNode(1)
        print self.PreOrderLoop(root=root)
# Solution().self_testing()

class Solution(object):
    # # InOrderLoop(TreeNode *root)
    # void InOrderLoop(TreeNode *root)
    # {
    #     std::stack<TreeNode *> s;
    # TreeNode *cur;
    # cur = root;
    # while (cur != NULL || !s.empty())
    # {
    # while (cur != NULL)
    #     {
    #         s.push(cur);
    #     cur = cur->left;
    #     }
    #
    #     cur = s.top();
    #     s.pop();
    #     printf("%c ", cur->data);
    #
    #     cur = cur->right;
    # }
    # }
    def InOrderLoop(self, root):
        s = stack()
        cur = root
        rst = []
        while(cur != None or not s.empty()):
            while(cur != None):
                s.push(cur)
                cur = cur.left
            cur = s.pop()
            rst.append(cur.val)

            cur = cur.right
        return rst

    def self_testing(self):
        root = TreeNode(1)
        root.left = TreeNode(2)
        root.right = TreeNode(3)
        root.left.right = TreeNode(5)
        print self.InOrderLoop(root=root)
        root = TreeNode(5)
        root.left = TreeNode(4)
        root.right = TreeNode(8)
        root.left.left = TreeNode(11)
        root.left.left.left = TreeNode(7)
        root.left.left.right = TreeNode(2)
        root.right.left = TreeNode(13)
        root.right.right = TreeNode(4)
        root.right.right.right = TreeNode(1)
        print self.InOrderLoop(root=root)

Solution().self_testing()

class Solution(object):
    # # PostOrderLoop
    # void PostOrderLoop(TreeNode *root)
    # {
    #     std::stack<TreeNode *> s;
    # TreeNode *cur, *top, *last = NULL;
    # cur = root;
    # while (cur != NULL || !s.empty())
    # {
    # while (cur != NULL)
    #     {
    #         s.push(cur);
    #     cur = cur->left;
    #     }
    #
    #     top = s.top();
    #
    #     if (top->right == NULL || top->right == last){
    #     s.pop();
    #     printf("%c ", top->data);
    #     last = top;
    #     }
    #     else {
    #     cur = top->right;
    #     }
    # }
    # }
    def PostOrderLoop(self, root):
        s = stack()
        cur = top = last = None
        cur = root
        rst = []
        while(cur != None or not s.empty()):
            while(cur != None):
                s.push(cur)
                cur = cur.left

            top = s.pick()
            if(top.right == None or top.right == last):
                s.pop()
                rst.append(top.val)
                last = top
            else:
                cur = top.right
        return rst
    def self_testing(self):
        root = TreeNode(1)
        root.left = TreeNode(2)
        root.right = TreeNode(3)
        root.left.right = TreeNode(5)
        print self.PostOrderLoop(root=root)
        root = TreeNode(5)
        root.left = TreeNode(4)
        root.right = TreeNode(8)
        root.left.left = TreeNode(11)
        root.left.left.left = TreeNode(7)
        root.left.left.right = TreeNode(2)
        root.right.left = TreeNode(13)
        root.right.right = TreeNode(4)
        root.right.right.right = TreeNode(1)
        print self.PostOrderLoop(root=root)

Solution().self_testing()

class Solution(object):
    # void LevelOrder(TreeNode *root)
    # {
    #     std::queue<TreeNode *> q;
    # TreeNode *front;
    #
    # if (root == NULL)return;
    #
    # q.push(root);
    #
    # while (!q.empty())
    # {
    #     front = q.front();
    # q.pop();
    #
    # if (front->left)
    # q.push(front->left);
    #
    # if (front->right)
    # q.push(front->right);
    #
    # printf("%c ", front->data);
    # }
    # }
    def LevelOrder(self, root):
        q = queue()
        front = None
        rst = []
        if(root == None): return rst
        q.push(root)
        while(not q.empty()):
            front = q.pop()
            if(front.left != None):
                q.push(front.left)
            if(front.right != None):
                q.push(front.right)
            rst.append(front.val)
        return rst

    def self_testing(self):
        root = TreeNode(1)
        root.left = TreeNode(2)
        root.right = TreeNode(3)
        root.left.right = TreeNode(5)
        print self.LevelOrder(root=root)
        root = TreeNode(5)
        root.left = TreeNode(4)
        root.right = TreeNode(8)
        root.left.left = TreeNode(11)
        root.left.left.left = TreeNode(7)
        root.left.left.right = TreeNode(2)
        root.right.left = TreeNode(13)
        root.right.right = TreeNode(4)
        root.right.right.right = TreeNode(1)
        print self.LevelOrder(root=root)

Solution().self_testing()

Reference

posted @ 2020-06-01 21:48  苏轶然  阅读(282)  评论(0编辑  收藏  举报