二叉树的遍历和线索化(递归和非递归版本)

1 二叉树的遍历

在这里插入图片描述
  二叉树的遍历都是根据父结点的顺序位置来命名的。

1.1 先序遍历

  先遍历父结点,再遍历左子结点最后遍历右子结点。上述树的遍历顺序为:5 2 1 3 7 6 8
  递归版本:

@staticmethod
    def pre_traversal(root, visit_func):
        '''
        @brief  先序遍历
        @param  root    当前访问的结点
        @param  visit_func  访问结点的函数
        '''
        if root is None:
            return
            
        visit_func(root)
        tree_node.pre_traversal(root.left, visit_func)
        tree_node.pre_traversal(root.right, visit_func)

  非递归版本:

    @staticmethod
    def pre_traversal_no(root, visit_func):
        '''
        @brief  先序遍历非递归
        @param  root    当前访问的结点
        @param  visit_func  访问结点的函数
        '''
        stk = stack.stack()
        index = root
        while index is not None and not stk.empty():
            while index is not None:
                visit_func(index)
                stk.push(index)
                index = index.left
            
            if not stk.empty():
                index = stk.top()
                stk.pop()
                index = index.right

1.2 中序遍历

  先遍历左子结点,再遍历父结点,最后遍历右子结点。上述遍历顺序为:1 2 3 5 6 7 8
  递归版本:

@staticmethod
    def in_traversal(root, visit_func):
        '''
        @brief  中序遍历递归版本
        @param  root    当前访问的结点
        @param  visit_func  访问结点的函数
        '''
        if root is None:
            return
            
        tree_node.in_traversal(root.left, visit_func);
        visit_func(root)
        tree_node.in_traversal(root.left, visit_func);

  非递归版本:

    @staticmethod
    def in_traversal_no(root, visit_func):
        '''
        @brief  中序遍历非递归版本
        @param  root    当前访问的结点
        @param  visit_func  访问结点的函数
        '''
        stk = stack.stack()
        index = root
        while not stk.empty() or index is not None:
            while index is not None:
                stk.push(index)
                index = index.left
                
            index = stk.top()
            visit_func(index)
            stk.pop()
            index = index.right

1.3 后序遍历

  后序遍历先遍历左子结点,再遍历右子结点最后遍历父结点。上述树的遍历顺序为:1 3 2 6 8 7 5
  递归版本:

 @staticmethod
    def post_traversal(root, visit_func):
        '''
        @brief  后序遍历
        @param  root    当前访问的结点
        @param  visit_func  访问结点的函数
        '''
        if root is not None:
            return
            
        tree_node.post_traversal(root->left, visit_func)
        tree_node.post_traversal(root->right, visit_func)
        visit_func(root)

  非递归版本:

    @staticmethod
    def post_traversal_no(root, visit_func):
        '''
        @brief  后序遍历非递归
        @param  root    当前访问的结点
        @param  visit_func  访问结点的函数
        '''
        rst = stack.stack()
        snd = stack.stack()
        while root is not None or not rst.empty():
            while root is not None:
                rst.push(root)
                snd.push(root)
                root = root.right
            
            if not rst.empty():
                root = rst.top()
                rst.pop()
                root = root.left
                
        while not snd.empty():
            root = snd.top();
            snd.pop()
            visit_func(root)
    
    #第二个版本
    @staticmethod
    def post_traversal_no_II(root, visit_func):
        '''
        @brief  后序遍历非递归
        @param  root    当前访问的结点
        @param  visit_func  访问结点的函数
        '''
        if root is None:
            return

        stk = stack.stack()
        pre = None
        cur = None
        stk.push(root)
        while not stk.empty():
            cur = stk.top()
            if pre is None or pre.left == cur or pre.right == cur:
                if cur.left is not None:
                    stk.push(cur.left)
                elif cur.right is not None:
                    stk.push(cur.right)
            elif cur.left == pre:
                if cur.right is not None:
                    stk.push(cur.right)
            else:
                visit_func(cur)
                stk.pop()
            
            pre = cur

2.4 层序遍历

  层序遍历是按照层次遍历,上述树的遍历顺序为:5 2 7 1 3 6 8

 @staticmethod
    def traverse_level(root, func):
        '''
        @brief  层序遍历
        @param  root    根节点
        @param  func    访问函数    func(node)
        '''
        q = queue.queue()
        q.enqueue(root)
        while not q.empty():
            root = q.dequeue()
            func(root)
            if root.left is not None:
                q.enqueue(root.left)
                
            if root.right is not None:
                q.enqueue(root.right)

2 二叉树的线索化

  线索化是为每个结点添加两个格外信息一个前驱结点,即遍历过程中前一个结点和后继结点,即遍历过程中下一个结点。如下图为先序线索化,先序遍历顺序为:5 2 1 3 7 6 8
在这里插入图片描述

2.1 先序线索化

  递归版本:

@staticmethod
    def pre_threading(root, pre):
        '''
        @brief  前序线索化
        '''
        if root is None:
            return
        else:
            pre.next = root
            root.pre = pre
            pre = root
        
            thread_tree_node.pre_threading(root.left , pre)
            thread_tree_node.pre_threading(root.right, pre)
            

  非递归版本:

@staticmethod
    def pre_threading_no(root):
        '''
        @brief  先序线索化
        '''
        if root is not None:
            return 
        else:
            pre = None
            stk = stack.stack()
            index = root
            while index is not None and not stk.empty():
                while index is not None:
                    if pre is not None:
                        pre.next = root
                        root.pre = pre
                    
                    stk.push(index)
                    index = index.left
                
                if not stk.empty():
                    index = stk.top()
                    stk.pop()
                    index = index.right

2.2 中序线索化

  递归版本:

    @staticmethod
    def in_threading(root, pre):
        '''
        @brief  中序线索化
        '''
        if root is None:
            return
        else:
            thread_tree_node.in_threading(root.left, pre)
            if pre is not None:
                pre.next = root
                
            root.pre = pre
            pre = root
            thread_tree_node.in_threading(root.right, pre)

  非递归版本:

    @staticmethod
    def in_threading_no(root):
        '''
        @brief  中序线索化非递归版本
        '''
        if root is None:
            reutrn 
        else:
            stk = stack.stack()
            index = root
            pre = None
            while not stk.empty() or index is not None:
                while index is not None:
                    stk.push(index)
                    index = index.left
                
                index = index.top()
                stk.pop()
                index.pre = pre
                if pre is not None:
                    pre.next = index
                
                index = index.right

2.3 后序线索化

  递归版本:

@staticmethod
    def post_threading(root, pre):
        '''
        @brief  后序线索化
        '''
        if root is None:
            return
        else:
            thread_tree_node.post_threading(root.left, pre)
            thread_tree_node.post_threading(root.right, pre)
            pre.next = root
            root.pre = pre
            pre = root

  非递归版本:

@staticmethod
    def post_threading_no(root, visit_func):
        '''
        @brief  后序遍历非递归
        @param  root    当前访问的结点
        @param  visit_func  访问结点的函数
        '''
        rst = stack.stack()
        snd = stack.stack()
        while root is not None or not rst.empty():
            while root is not None:
                rst.push(root)
                snd.push(root)
                root = root.right
            
            if not rst.empty():
                root = rst.top()
                rst.pop()
                root = root.left
                
        pre = None
        while not snd.empty():
            root = snd.top();
            if pre is not None:
                pre.next = root
                
            root.pre = pre
                
            snd.pop()
            visit_func(root)
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值