數據結構和算法-二叉樹

二叉樹的兩顆子樹有明確的左右之分.
說子樹時必須說明是左子樹/右子樹. 根節點從1開始計數. 高度和深度是從0開始, 層數是從1開始node

  • 在非空二叉樹第i層中至多有2**(i-1)次方個結點
  • 在高度爲h的二叉樹總結點數最多爲2**(h+1)-1個結點
  • 序號爲1的點是根
  • 對於i>0, 其父節點的編號是i/2
  • 若是節點i有左右子節點, 那麼左子樹編號是2*i, 右節點編號是2*i+1

種類

  • 滿二叉樹
    除了葉子節點外其它節點都有左右子節點
  • 徹底二叉樹
    葉子節點在最底下兩層, 最後一層的葉子節點都靠左排列. 除了最後一層其它層的節點個數達到最大

存儲方式

  • 鏈式存儲法(鏈表)
  • 順序存儲法(數組)
    若是一棵樹是徹底二叉樹, 那麼使用數組存儲是最節省空間的方式

遍歷

遍歷即將樹的全部結點訪問一次, 按照節點位置的不一樣分爲前序遍歷, 中序遍歷, 後序遍歷python

  • 前序遍歷: 根節點-->左子樹-->右子樹 (DBACEGF)
  • 中序遍歷: 左子樹-->根節點-->右子樹 (ABCDEFG)
  • 後序遍歷: 左子樹-->右子樹-->根節點 (ACBFGED)
# 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
"""

深度優先遍歷

使用棧app

# 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"]

根據前序遍歷和中序遍歷, 求後續遍歷

分析: 前序遍歷的第一個值就是根節點, 而後在中序遍歷中找到這個值, 那麼這個值的左邊部分就是當前二叉樹的左子樹部分中序遍歷結果, 這個值的右邊部分就是當前二叉樹的右子樹部分中序遍歷結果. 所以, 經過這個分析, 能夠恢復這顆二叉樹code

#!/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

相關文章
相關標籤/搜索