数据结构-二叉树--二叉搜索树

# 二叉树

class BiTreeNode:
    def __init__(self, data):
        self.data = data
        self.lchild = None
        self.rchild = None


a = BiTreeNode('A')
b = BiTreeNode('B')
c = BiTreeNode('C')
d = BiTreeNode('D')
e = BiTreeNode('E')
f = BiTreeNode('F')
g = BiTreeNode('G')

e.lchild = a
e.rchild = g
a.rchild = c
g.rchild = f
c.lchild = b
c.rchild = d

root = e


# DFS深度优先遍历
def pre_order(root):  # 前序遍历
    if root:
        print(root.data, end='->')
        pre_order(root.lchild)
        pre_order(root.rchild)


def in_order(root):  # 中序遍历
    if root:
        in_order(root.lchild)
        print(root.data, end="->")
        in_order(root.rchild)


def post_order(root):  # 后序遍历
    if root:
        post_order(root.lchild)
        post_order(root.rchild)
        print(root.data, end="->")


#
# pre_order(root)  # E->A->C->B->D->G->F->
# print()
# in_order(root)  # A->B->C->D->E->G->F->
# print()
# post_order(root)  # B->D->C->A->F->G->E->

# 层次遍历
# 广度优先,父节点进队,父节点出队的时候  子节点全部进队--队列
from collections import deque


def level_order(root):
    q = deque()
    q.append(root)
    while (len(q) > 0):
        node = q.popleft()
        print('%s' % node.data, end='')
        if node.lchild:
            q.append(node.lchild)
        if node.rchild:
            q.append(node.rchild)


# level_order(root)  # EAGCFBD


# 二叉搜索树:首先是一个二叉树,其次该树中每个树的左子节点的key<=右子节点的key,右节点>=左节点
# 查找的时间复杂度:logn
# 插入:logn
# BST  binary search tree


# 二叉搜索树的中序序列是升序的


class BST:
    def __init__(self, li):
        self.root = None
        for val in li:
            self.insert(val)

    def travese_inorder(self):
        def in_order(root):  # 中序遍历--升序
            if root:
                in_order(root.lchild)
                print(root.data, end=",")
                in_order(root.rchild)

        in_order(self.root)

    def insert(self, key):
        if not self.root:
            self.root = BiTreeNode(key)
        else:
            p = self.root
            while p:
                if key < p.data:  # 左边走
                    if not p.lchild:
                        p.lchild = BiTreeNode(key)
                        break
                    else:
                        p = p.lchild
                else:  # 右边走
                    if not p.rchild:
                        p.rchild = BiTreeNode(key)
                        break
                    else:
                        p = p.rchild

    def __contains__(self, item):
        p = self.root
        while p:
            if item == p.data:
                return True
            elif item < p.data:
                p = p.lchild
            else:
                p = p.rchild
        return False


bst = BST([5, 4, 3, 1, 2, 7, 8])
print(222 in bst)

#最坏的情况是:非常偏斜的树
例题:知道一个二叉树的前序序列和中序序列,代码实现二叉树并返回root节点
class BinaryTreeNode:
    def __init__(self, data: int):
        self.data = data
        self.lchild = None
        self.rchild = None

    def __str__(self):
        return '%d' % self.data

    @staticmethod
    def preorder(root):
        if root:
            print(root.data, end='')
            BinaryTreeNode.preorder(root.lchild)
            BinaryTreeNode.preorder(root.rchild)

    @staticmethod
    def inorder(root):
        if root:
            BinaryTreeNode.inorder(root.lchild)
            print(root.data, end='')
            BinaryTreeNode.inorder(root.rchild)


def construct_bt(preorder: list, inorder: list):
    if not preorder or not inorder or len(preorder) != len(inorder):
        raise KeyError('invalid input')
    return constructCore(0, len(preorder) - 1, 0, len(inorder) - 1, preorder, inorder)


def constructCore(startPreorder: int, endPreorder: int, startInoder: int, endInorder: int, preorder: list,
                  inorder: list):
    if (startPreorder == endPreorder):
        if (startInoder == endInorder):
            #递归终结
            root_data = preorder[startPreorder]
            root = BinaryTreeNode(root_data)
            return root
        else:
            raise Exception('invalid input')
    else:
        root_data = preorder[startPreorder:endPreorder][0]
        root = BinaryTreeNode(root_data)
    # 在中序序列中找到根节点的索引,该根节点的<索引是左节点,>索引是右节点
    rootInorder = startInoder
    for index, val in enumerate(inorder):
        if val == root_data:
            rootInorder = index
            break
    leftLength = rootInorder - startInoder  # 左节点的数量
    leftPreorderEnd = startPreorder + leftLength  # 前序序列中左节点的末尾index
    if leftLength > 0:
        # 构建左子树
        root.lchild = constructCore(startPreorder + 1, leftPreorderEnd, startInoder, rootInorder - 1, preorder, inorder)#左节点的前序范围,左节点的中序范围
    if leftLength < endPreorder - startPreorder:
        # 构建右子树
        root.rchild = constructCore(leftPreorderEnd + 1, endPreorder, rootInorder + 1, endInorder, preorder, inorder)#右节点的前序范围,右节点的中序范围
    return root


preorder = [1, 2, 4, 7, 3, 5, 6, 8]
inorder = [4, 7, 2, 1, 5, 3, 8, 6]
root = construct_bt(preorder, inorder)
root

# BinaryTreeNode.preorder(root)
# print()
# BinaryTreeNode.inorder(root)
posted @ 2020-04-20 10:31  烧刘病  阅读(127)  评论(0编辑  收藏  举报
回到页首