数据结构和算法-二叉树

二叉树的两颗子树有明确的左右之分.
说子树时必须说明是左子树/右子树. 根节点从1开始计数. 高度和深度是从0开始, 层数是从1开始

  • 在非空二叉树第i层中至多有2**(i-1)次方个结点
  • 在高度为h的二叉树总结点数最多为2**(h+1)-1个结点
  • 序号为1的点是根
  • 对于i>0, 其父节点的编号是i/2
  • 如果节点i有左右子节点, 那么左子树编号是2*i, 右节点编号是2*i+1

种类

  • 满二叉树
    除了叶子节点外其它节点都有左右子节点
  • 完全二叉树
    叶子节点在最底下两层, 最后一层的叶子节点都靠左排列. 除了最后一层其它层的节点个数达到最大

存储方式

  • 链式存储法(链表)
  • 顺序存储法(数组)
    如果一棵树是完全二叉树, 那么使用数组存储是最节省空间的方式

遍历

遍历即将树的所有结点访问一次, 按照节点位置的不同分为前序遍历, 中序遍历, 后序遍历

  • 前序遍历: 根节点-->左子树-->右子树 (DBACEGF)
  • 中序遍历: 左子树-->根节点-->右子树 (ABCDEFG)
  • 后序遍历: 左子树-->右子树-->根节点 (ACBFGED)
    1634914-20190612202927732-181561477.png
# coding:utf-8


"""
二叉树遍历
时间复杂度: O(n)
"""


class BinaryTree(object):
    def __init__(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right


def pre(root):
    """前序遍历"""
    if root is None:
        return
    print(root.data, end="")
    pre(root.left)
    pre(root.right)


def mid(root):
    """中序遍历"""
    if root is None:
        return
    pre(root.left)
    print(root.data, end="")
    pre(root.right)


def after(root):
    """后续遍历"""
    if root is None:
        return
    pre(root.left)
    pre(root.right)
    print(root.data, end="")


def level(root):
    """
    按层级遍历, 广度优先遍历
    :param root:
    :return:
    """
    from collections import deque

    d = deque([])
    d.append(root)
    while d:
        node = d.popleft()
        print(node.data, end="")
        if node.left:
            d.append(node.left)
        if node.right:
            d.append(node.right)


if __name__ == '__main__':
    root = BinaryTree(
        'D',
        BinaryTree(
            'B',
            BinaryTree('A'),
            BinaryTree('C')
        ),
        BinaryTree(
            'E',
            right=BinaryTree(
                'G',
                BinaryTree('F')
            )
        )
    )
    pre(root)
    print("\n")
    mid(root)
    print("\n")
    after(root)
    print("\n")
    level(root)

"""
DBACEGF

BACDEGF

BACEGFD

DBEACGF
"""

广度优先

使用队列

# coding:utf-8

from collections import deque

class Node(object):
    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right


def width(root):
    if root is None:
        return
    queue = []
    d = deque(queue)
    d.append(root)

    while d:
        node = d.popleft()
        print(node.value),
        if node.left:
            d.append(node.left)
        if node.right:
            d.append(node.right)


if __name__ == '__main__':
    root = Node('D',Node('B',Node('A'),Node('C')),Node('E',right=Node('G',Node('F'))))
    width(root)




"""
D B E A C G F
"""

深度优先遍历

使用栈

# coding:utf-8

"""
深度优先遍历
"""

from collections import deque


class Node(object):
    def __init__(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right


def depth(root):
    if root is None:
        return
    res = []

    d = deque([])
    d.append(root)
    while d:
        node = d.pop()
        res.append(node.data)
        if node.right:
            d.append(node.right)
        if node.left:
            d.append(node.left)

    return res


if __name__ == '__main__':
    root = Node('D', Node('B', Node('A'), Node('C')), Node('E', right=Node('G', Node('F'))))
    res = depth(root)
    assert res == ["D", "B", "A", "C", "E", "G", "F"]

根据前序遍历和中序遍历, 求后续遍历

分析: 前序遍历的第一个值就是根节点, 然后在中序遍历中找到这个值, 那么这个值的左边部分就是当前二叉树的左子树部分中序遍历结果, 这个值的右边部分就是当前二叉树的右子树部分中序遍历结果. 因此, 通过这个分析, 可以恢复这颗二叉树

#!/usr/bin/env python
# coding:utf-8

pre = list('DBACEGF')
mid = list('ABCDEFG')
after = []

def find_after_tree(pre, mid, after):
    if len(pre) == 0:
        return
    if len(pre) == 1:
        after.append(pre[0])
        return
    # 根据前序遍历得到根节点
    root = pre[0]
    # 在中序遍历中得到根节点的位置, 那么左半部分就是左子树, 另外是右子树
    n = mid.index(root)
    find_after_tree(pre[1:n+1], mid[:n], after)
    find_after_tree(pre[n+1:], mid[n+1:], after)
    # 最后把根节点添加进去
    after.append(root)

find_after_tree(pre, mid, after)
print after


"""
['A', 'C', 'B', 'F', 'G', 'E', 'D']
"""

求最大树深

# coding:utf-8

"""
求最大树深
"""

def get_max_depth(root):
    if root is None:
        return -1
    return max(get_max_depth(root.left), get_max_depth(root.right)) + 1

求两个树是否相同

# coding:utf-8

"""
求两个树是否完全相同
"""


def is_same_tree(tree1, tree2):
    if tree1 is None and tree2 is None:
        return True
    elif tree1 and tree2:
        return tree1.data == tree2.data and is_same_tree(tree1.left, tree2.left) and is_same_tree(tree1.right,
                                                                                                  tree2.right)
    else:
        return False

1634914-20190623172836409-113676237.jpg

转载于:https://www.cnblogs.com/zlone/p/11012109.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值