Python数据结构与算法—树形结构、二叉树

基础概念

1.定义:树(Tree)是n(n≥0)个节点的有限集合T,它知足两个条件:有且仅有一个特定的称为根(Root)的节点;其他的节点能够分为m(m≥0)个互不相交的有限集合T一、T二、……、Tm,其中每个集合又是一棵树,并称为其根的子树(Subtree)。node

2.基本概念ide

  • 一个节点的子树的个数称为该节点的度数,一棵树的度数是指该树中节点的最大度数。
  • 度数为零的节点称为树叶或终端节点,度数不为零的节点称为分支节点,除根节点外的分支节点称为内部节点。
  • 一个节点的子树之根节点称为该节点的子节点,该节点称为它们的父节点,同一节点的各个子节点之间称为兄弟节点。一棵树的根节点没有父节点,叶节点没有子节点。
  • 一个节点系列k1,k2, ……,ki,ki+1, ……,kj,并知足ki是ki+1的父节点,就称为一条从k1到kj的路径,路径的长度为j-1,即路径中的边数。路径中前面的节点是后面节点的祖先,后面节点是前面节点的子孙。
  • 节点的层数等于父节点的层数加一,根节点的层数定义为一。树中节点层数的最大值称为该树的高度或深度。
  • m(m≥0)棵互不相交的树的集合称为森林。树去掉根节点就成为森林,森林加上一个新的根节点就成为树。

二叉树

定义与特征

1.定义:二叉树(Binary Tree)是n(n≥0)个节点的有限集合,它或者是空集(n=0),或者是由一个根节点以及两棵互不相交的、分别称为左子树和右子树的二叉树组成。二叉树与普通有序树不一样,二叉树严格区分左孩子和右孩子,即便只有一个子节点也要区分左右。函数

2.二叉树的特征post

  • 二叉树第i(i≥1)层上的节点最多为2^{i-1}2i1个。
  • 深度为k(k≥1)的二叉树最多有2^k-12k1个节点。
  • 在任意一棵二叉树中,树叶的数目比度数为2的节点的数目多一。
  • 满二叉树 :深度为k(k≥1)时有2^k-12k1个节点的二叉树。
  • 彻底二叉树 :只有最下面两层有度数小于2的节点,且最下面一层的叶节点集中在最左边的若干位置上。

二叉树的遍历

遍历 :沿某条搜索路径周游二叉树,对树中的每个节点访问一次且仅访问一次。spa

先序遍历: 先访问树根,再访问左子树,最后访问右子树;
中序遍历: 先访问左子树,再访问树根,最后访问右子树;
后序遍历: 先访问左子树,再访问右子树,最后访问树根;
层次遍历: 从根节点开始,逐层从左向右进行遍历。设计

递归思想和实践

1.什么是递归?code

所谓递归函数是指一个函数的函数体中直接调用或间接调用了该函数自身的函数。这里的直接调用是指一个函数的函数体中含有调用自身的语句,间接调用是指一个函数在函数体里有调用了其它函数,而其它函数又反过来调用了该函数的状况。对象

2.递归函数调用的执行过程分为两个阶段blog

递推阶段:从原问题出发,按递归公式递推从未知到已知,最终达到递归终止条件。
回归阶段:按递归终止条件求出结果,逆向逐步代入递归公式,回归到原问题求解。递归

3.优势与缺点

优势:递归能够把问题简单化,让思路更为清晰,代码更简洁
缺点:递归因系统环境影响大,当递归深度太大时,可能会获得不可预知的结果

# 求n的阶乘
def recursion(n): # 递归终止条件
  if n < 1: return 1
  return n * recursion(n - 1) print("n!=",recursion(5))

二叉树的代码实现

二叉树顺序存储

二叉树自己是一种递归结构,能够使用Python list 进行存储。可是若是二叉树的结构比较稀疏的话浪费的空间是比较多的。

  • 空结点用None表示
  • 非空二叉树用包含三个元素的列表[d,l,r]表示,其中d表示根结点,l,r左子树和右子树。
 1 ['A',['B',None,None  2  ],  3      ['C',['D',['F',None,None],  4                ['G',None,None],  5  ],  6           ['E',['H',None,None],  7                ['I',None,None],  8  ],  9  ] 10 ]
顺序存储代码
 1 bitree.py 二叉树的实现  2 
 3 思路分析:   4 1. 使用链式存储  5   节点类设计上有两个属性变量引用左孩子和右孩子  6 2. 操做类完成二叉树的遍历  7 """
 8 from day2.squeue import SQueue  9 
10 # 二叉树节点 11 class TreeNode: 12  def __init__(self, data=None, left=None, right=None): 13  self.data = data 14  self.left = left 15  self.right = right 16 
17 #  二叉树操做 18 class Bitree: 19  def __init__(self, root=None): 20  self.root = root # 获取树根 21 
22  # 先序遍历 23  def preOrder(self,node): 24  if node is None: 25  return 26  print(node.data,end=' ') 27  self.preOrder(node.left) 28  self.preOrder(node.right) 29 
30  #  中序遍历 31  def inOrder(self, node): 32  if node is None: 33  return 34  self.inOrder(node.left) 35  print(node.data, end=' ') 36  self.inOrder(node.right) 37 
38  #  后序遍历 39  def postOrder(self, node): 40  if node is None: 41  return 42  self.postOrder(node.left) 43  self.postOrder(node.right) 44  print(node.data, end=' ') 45 
46  # 层次遍历 47  def levelOrder(self,node): 48  sq = SQueue() 49  sq.enqueue(node) # 从node遍历 50  while not sq.is_empty(): 51  node = sq.dequeue() # 出队一个 52  print(node.data,end=' ') # 遍历数据 53  if node.left: 54  sq.enqueue(node.left) 55  if node.right: 56  sq.enqueue(node.right) 57 
58 if __name__ == "__main__": 59  #  后序遍历 BFGDIHECA 60  # 构建树 (笔记中) 61  b = TreeNode('B') 62  f = TreeNode('F') 63  g = TreeNode('G') 64  d = TreeNode('D', f, g) 65  i = TreeNode('I') 66  h = TreeNode('H') 67  e = TreeNode('E', i, h) 68  c = TreeNode('C', d, e) 69  a = TreeNode('A', b, c) # 树根 70 
71  #  初始化树对象,获得树根 72  bt = Bitree(a) 73  # 先序 74  bt.preOrder(bt.root) 75  print() 76  #  中序 77  bt.inOrder(bt.root) 78  print() 79  bt.postOrder(bt.root) 80  print() 81  bt.levelOrder(bt.root) 82  print()
链式存储代码