数据结构-二叉树遍历

栏目: 数据库 · 发布时间: 5年前

导语

  • 贪心法涉及到的图论部分,头大,计算下工作量,基本等于数据结构部分重新刷完了.
  • 直接开始数据结构部分,图论等按顺序来.
  • 下一篇是排序.

二叉树基础

  • 二叉树(英语:Binary tree)是每个节点最多只有两个分支的树结构。通常分支被称作“左子树”或“右子树”.
  • 满二叉树/完全二叉树
    • 深度为 $k$ 的二叉树最多拥有 $2^{k+1}-1$ 个节点.(根节点的深度定义为$k_0 = 0$)
    • 深度为 $k$ 拥有 $2^{k+1}-1$ 个节点的二叉树称为满二叉树(每一层都满员)
    • 而深度为 $k$ 有 $n$ 个节点的二叉树,当且仅当每个节点都与深度为 $k$ 的满二叉树序号由1到n一一对应时,称为完全二叉树.(前k-1层,满员,第k层,叶子节点聚集在左侧,可能满也可能不满.)
  • 二叉树存储

    • 数组
      • 第k个节点,对应左子树为2k,右子树为2k+1.第0个节点置空.(随意)
      • 非常方便寻址,且块存储,不易碎片化.
      • 对于非满/完全二叉树,有可能存在空间浪费.
    • 二叉链表
      • 仿照二叉树结构,在数据结构中加入左子树/右子树地址.
      • 节约空间,易碎片化,寻址等稍繁琐.
    • 数据结构中可能会用到两种,这里随机生成一个数组,且在数据结构定义中加入左/右子树地址,并链接.
    • 数据值域因为python为动态语言,这里限定仅为 int 和 str 类型.
  • 源码:

    #!/usr/bin/python3
    import random
    import copy
    import string
    
    
    class BtNode(object):
        def __init__(self, value=0, leftBt=None, rightBt=None):
            self.value = value
            self.lchild = leftBt
            self.rchild = rightBt
    
        @property
        def value(self):
            return self._value
    
        @value.setter
        def value(self, values):
            if not (isinstance(values, int) or isinstance(values, str)):
                raise ValueError('value must be an int or str!')
            self._value = values
    
        @property
        def lchild(self):
            return self._lchild
    
        @lchild.setter
        def lchild(self, leftBt):
            if not (isinstance(leftBt, BtNode) or (leftBt is None)):
                raise ValueError('leftBt must be BtNode')
            self._lchild = leftBt
    
        @property
        def rchild(self):
            return self._rchild
    
        @rchild.setter
        def rchild(self, rightBt):
            if not (isinstance(rightBt, BtNode) or (rightBt is None)):
                raise ValueError('rightBt must be BtNode')
            self._rchild = rightBt
    
    
    class Btree(object):
        def __init__(self, len=50):
            self.__len = len
            self.__arr = [BtNode() for i in range(self.__len)]
            self.__link()
    
        def Cr_int(self):
            self.__arr = list(map(self.__randomint, self.__arr))
            return copy.deepcopy(self.__arr)
    
        def Cr_str(self, len=50):
            self.__arr = list(map(self.__randomstr, self.__arr))
            return copy.deepcopy(self.__arr)
    
        def __link(self):
            for i in range(self.__len - 1, 1, -1):
                if (i % 2) == 1:
                    self.__arr[i // 2].rchild = self.__arr[i]
                else:
                    self.__arr[i // 2].lchild = self.__arr[i]
    
        def __randomint(self, btNode):
            btNode.value = random.randint(0, 100)
            return btNode
    
        def __randomstr(self, btNode):
            btNode.value = ''.join(random.choices(string.ascii_lowercase, k=1))
            return btNode
    
        @classmethod
        def visit(self, node):
            return print(node.value, end=' ')
    
  • 测试代码

    #!/usr/bin/python3
    import unittest
    from bt_base import BtNode, Btree
    
    
    class test_bt(unittest.TestCase):
        def test_BtNode(self):
            tmp = BtNode()
            self.assertEqual(tmp.value, 0)
            self.assertEqual(tmp.lchild, None)
            self.assertEqual(tmp.rchild, None)
            with self.assertRaises(ValueError):
                tmp.value = 1.3
            with self.assertRaises(ValueError):
                tmp.lchild = 1.3
            with self.assertRaises(ValueError):
                tmp.rchild = 1.3
    
        def test_Btree(self):
            bt = Btree()
            tmp = bt.Cr_int()
            for node in tmp:
                self.assertTrue(isinstance(node, BtNode))
                self.assertTrue(isinstance(node.value, int))
                self.assertTrue(isinstance(node.lchild, (BtNode, type(None))))
                self.assertTrue(isinstance(node.rchild, (BtNode, type(None))))
            tmp = bt.Cr_str()
            for node in tmp:
                self.assertTrue(isinstance(node, BtNode))
                self.assertTrue(isinstance(node.value, str))
                self.assertTrue(isinstance(node.lchild, (BtNode, type(None))))
                self.assertTrue(isinstance(node.rchild, (BtNode, type(None))))
    

二叉树遍历

  • 二叉树遍历按遍历方式分为3种,每种又有递归和循环两种写法.

    • 先序遍历: 节点值->左子树->右子树
    • 中序遍历: 左子树->节点值->右子树
    • 后序遍历: 左子树->右子树->节点值
  • 代码比较简单,配合python与伪代码相差不大,没写注释.

  • 代码

    • 递归

      @classmethod
      def Pre_Order_Re(self, root):
          if root:
              Btree.visit(root)
          if root.lchild:
              self.Pre_Order_Re(root.lchild)
          if root.rchild:
              self.Pre_Order_Re(root.rchild)
      
      @classmethod
      def In_Order_Re(self, root):
          if root.lchild:
              self.In_Order_Re(root.lchild)
          if root:
              Btree.visit(root)
          if root.rchild:
              self.In_Order_Re(root.rchild)
      
      @classmethod
      def Post_Order_Re(self, root):
          if root.lchild:
              self.Post_Order_Re(root.lchild)
          if root.rchild:
              self.Post_Order_Re(root.rchild)
          if root:
              Btree.visit(root)
      
    • 循环

          @classmethod
      def Pre_Order_loop(self, root):
          stack = []
          stack.append(root)
          while stack:
              p = stack.pop()
              Btree.visit(p)
              if p.rchild:
                  stack.append(p.rchild)
              if p.lchild:
                  stack.append(p.lchild)
      
      @classmethod
      def In_Order_loop(self, root):
          stack = []
          p = root
          while stack or p:
              while p:
                  stack.append(p)
                  p = p.lchild
              if stack:
                  p = stack.pop()
                  Btree.visit(p)
                  p = p.rchild
      
      @classmethod
      def Post_Order_loop(self, root):
          stack = []
          stackb = []
          stack.append(root)
          while stack:
              p = stack.pop()
              stackb.append(p)
              if p.lchild:
                  stack.append(p.lchild)
              if p.rchild:
                  stack.append(p.rchild)
          while stackb:
              Btree.visit(stackb.pop())
      
  • 说明:

    • 递归代码非常明了,但没有尾递归优化的语言,可能存在堆栈溢出.
    • 先序遍历循环写法,利用了一个堆栈来实现,受益于python,与伪代码非常接近.
    • 中序遍历循环写法,与先序遍历循环相似,特殊一点的时,在遍历完根节点的左子树时,堆栈为空,但p不为空,循环条件判断时,针对这种情况要做相应处理.
    • 后序遍历循环写法,可以实现的方式不唯一,这里是更改先序遍历,将顺序更改为后序遍历的逆过程,不断将结果压入另一个堆栈,最后从这个堆栈中释放,得到后序遍历的正确顺序.

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

构建高性能Web站点

构建高性能Web站点

郭欣 / 电子工业出版社 / 2009-8 / 59.00元

本书围绕如何构建高性能Web站点,从多个方面、多个角度进行了全面的阐述,涵盖了Web站点性能优化的几乎所有内容,包括数据的网络传输、服务器并发处理能力、动态网页缓存、动态网页静态化、应用层数据缓存、分布式缓存、Web服务器缓存、反向代理缓存、脚本解释速度、页面组件分离、浏览器本地缓存、浏览器并发请求、文件的分发、数据库I/O优化、数据库访问、数据库分布式设计、负载均衡、分布式文件系统、性能监控等。......一起来看看 《构建高性能Web站点》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具