# 二叉树
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)