数据结构 —— 二叉树(Python实现)

来源:互联网 发布:cordic算法看哪本书 编辑:程序博客网 时间:2024/06/04 18:39

1. 树

(1)特点

a. 不为空
b. 子树不分次序
c. 至少有1个根结点
d. 一个结点可以有多个子树

(2)树的度

结点的度:一个结点拥有的子树个数
树的(横向):树中结点最大的度

(3)树的高度

树的高度(纵向):树的层数

(4)性质

a. 高度为h的树最多有2h-1个结点(满二叉树)

2. 二叉树

(1)特点

a. 可以为
b. 子树分‘左右子树
c. 一个结点最多2个子树

(2)性质

a. 二叉树的第i层最多有2i-1个结点
b. 包含n个结点的二叉树,高度至少为[log2(n+1)] (此处的[x]表示不小于x的最小整数)
c. 任意一颗二叉树,若a个叶子结点,有b个度为2的结点,则:a=b+1
d. 满二叉树:高度为h,有2h-1个结点的树
e. 完全二叉树:只有最下面两层结点的度<2,且最下一层的叶子结点都集中在左子树

3. 二叉树的遍历

这里写图片描述

(1)先序遍历

ABC DEH FGK (最后一个是最右最下结点)

(2)中序遍历

DB FEG AC KH (最后一个是最右结点)

(3)后序遍历

DFG EB KHC A (最后一个是根节点)

4. 二叉树的python代码实现

目的:打印一棵二叉树
要求:宽度优先遍历
1.遍历二叉树:从根节点开始,从上往下,从左到右
2.依次打印出这些结点

'''变量含义:    1.last:指向二叉树当前层的最右结点(换层标识)    2.nlast:指向当前从二叉树上取出的结点的左右孩子,一般遍历完一层之后nlast都指向当前             层最右结点的右孩子    3.node:表示当前从queue取出并放入temp的那个结点    4.queue:列表,用来存放二叉树的结点    5.res:列表,用来存放最终待打印的结点    6.temp:列表,用来临时存放二叉树每一层的节点过程:    二叉树——>queue——>temp——>res    1.上到下:遍历二叉树,按层一个个获取结点    2.左到右:把获取的节点node + 节点左孩子node.left + 节点右孩子node.right——>             queue(即:用队列形式来存储二叉树节点)。 此时:             last指向获取的节点所在层的最右节点,             nlast指向当前节点的右孩子,即:last在nlast的上一层    3.遍历:把当前获取的节点node——>temp,然后继续从queue获取队头(可能是node的兄弟),           在上一步他们曾作为左右孩子加入了queue    4.换层:当node=last时,即:获取到当前层的最右节点时,表示此层遍历完毕,此时需要把           此层结点(在temp中)——>res    5.一层层遍历完后,打印出res'''# 定义一个二叉树类,存放"结点的初始化"函数class TreeNode:    def __init__(self,x):   # 初始化结点x        self.val = x     # 结点的值为x        self.left = None    # 结点的左孩子初始化为空        self.right = None   # 结点的右孩子初始化为空# 定义一个打印二叉树的类,存放"打印二叉树的方法"class TreePrinter:    def printTree(self,root):        queue = []    # 定义一个队列,用来存放二叉树中的结点(原始)        temp = []     # 定义一个临时列表,用来存放每一层遍历出的结点 (临时)        res = []      # 定义一个空列表,用来存放最终供打印输出的结点(最终)        if root == None:     # 如果根节点为空,证明此二叉树为空            return res       # 则返回空列表        last = nlast = root   # 设定last和nlast最初都指向root        queue.append(root)    # 首先将二叉树的第一个结点(即root结点)存入queue队列        # 当queue的长度不为0(即:此二叉树不为空)时,执行此循环        while len(queue):                 # 先从队列头开始取结点,把取出的结点赋给变量node(最开始弹出的是根节点)            node = queue.pop(0)  # node表示此刻从queue中取出的结点              # 再将从队列中取出的结点暂时放进临时列表temp中                                          temp.append(node.val)                # 获取左右孩子结点            if node.left != None:     # 如果从queue取出的这个结点有左孩子                queue.append(node.left)     # 那就把左孩子也存入queue队列                nlast = node.left           # 并让nlast指向左孩子            if node.right != Nine:    # 如果弹出的这个结点有右孩子                queue.append(node.right)    # 把此结点的右孩子也存入queue队列中                nlast = node.right          # 并让nlast指向右孩子            # 当前层取完,为取下一层结点做准备            # 若当前取的结点=last,即:此刻取的是当前层的最右结点,意味着即将走到下一层            if node == last:                    res.append(temp[:])   # 把temp中的所有结点存入res列表                temp = []     #  把temp重置为空列表,使它能继续存放下一层的结点                last = nlast     # 换行:此时nlast指向当前层最右节点的右孩子,让last跳到下一层的最右节点        return res