数据结构 10. 二叉树

一、二叉树

1. 定义

二叉查找树(Binary Search Tree),又称为二叉搜索树、二叉排序树。其或者是一棵空树;或者是具有以下性质的二叉树:

  • 若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值
  • 若左子树不空,则左子树上所有结点的值均小于或等于它的根结点的值
  • 左、右子树也分别为二叉排序树

类(TreeNode):定义二叉搜索树各个节点
在该类中,分别存放节点本身的值,以及其左子节点,右子节点,根节点的值。

在这里插入图片描述

2. 实现一个二叉查找树,并且支持插入、删除、查找操作

2.1 查找和插入

当二叉查找树不为空时:

  • 首先将给定值与根结点的关键字比较,若相等,则查找成功
  • 若小于根结点的关键字值,递归查左子树
  • 若大于根结点的关键字值,递归查右子树
  • 若子树为空,查找不成功

二叉排序树是一种动态树表。其特点是:树的结构通常不是一次生成的,而是在查找过程中,当树中不存在关键字等于给定值的结点时再进行插入。新插入的结点一定是一个新添加的叶子结点,并且是查找不成功时查找路径上访问的最后一个结点的左孩子或右孩子结点。如下图所示:

在这里插入图片描述

2.2 删除

二叉查找树的删除操作分为三种情况:

  1. 如果待删除的节点是叶子节点,那么可以立即被删除,如下图所示:

在这里插入图片描述
2. 如果节点只有一个儿子,则将此节点parent的指针指向此节点的儿子,然后删除节点,如下图所示:

在这里插入图片描述

  • 如果节点有两个儿子,则将其右子树的最小数据代替此节点的数据,并将其右子树的最小数据删除,如下图所示:
    在这里插入图片描述

3. 实现二叉树前、中、后序以及按层遍历

在这里插入图片描述

3.1 先序遍历

访问顺序如下:

  • 访问根节点
  • 先序遍历左子树
  • 先序遍历右子树

以图 1为例,访问顺序为:4,2,1,3,5,6

3.2 中序遍历

访问顺序如下:

  • 中序遍历左子树
  • 访问根节点
  • 中序遍历右子树

以图 1为例,访问顺序为:1,2,3,4,5,6

3.3 后序遍历

访问顺序如下:

  • 后序遍历左子树
  • 后序遍历右子树
  • 访问根节点

以图 1为例,访问顺序为:1,3,2,6,5,4

# encoding: utf-8
class Node:
    def __init__(self, data):
        self.data = data
        self.lchild = None
        self.rchild = None
 
class BST:
    def __init__(self, node_list):
        self.root = Node(node_list[0])
        for data in node_list[1:]:
            self.insert(data)
 
    # 搜索
    def search(self, node, parent, data):
        if node is None:
            return False, node, parent
        if node.data == data:
            return True, node, parent
        if node.data > data:
            return self.search(node.lchild, node, data)
        else:
            return self.search(node.rchild, node, data)
 
    # 插入
    def insert(self, data):
        flag, n, p = self.search(self.root, self.root, data)
        if not flag:
            new_node = Node(data)
            if data > p.data:
                p.rchild = new_node
            else:
                p.lchild = new_node
 
    # 删除
    def delete(self, root, data):
        flag, n, p = self.search(root, root, data)
        if flag is False:
            print "无该关键字,删除失败"
        else:
            if n.lchild is None:
                if n == p.lchild:
                    p.lchild = n.rchild
                else:
                    p.rchild = n.rchild
                del p
            elif n.rchild is None:
                if n == p.lchild:
                    p.lchild = n.lchild
                else:
                    p.rchild = n.lchild
                del p
            else:  # 左右子树均不为空
                pre = n.rchild
                if pre.lchild is None:
                    n.data = pre.data
                    n.rchild = pre.rchild
                    del pre
                else:
                    next = pre.lchild
                    while next.lchild is not None:
                        pre = next
                        next = next.lchild
                    n.data = next.data
                    pre.lchild = next.rchild
                    del p
 
 
    # 先序遍历
    def preOrderTraverse(self, node):
        if node is not None:
            print node.data,
            self.preOrderTraverse(node.lchild)
            self.preOrderTraverse(node.rchild)
 
    # 中序遍历
    def inOrderTraverse(self, node):
        if node is not None:
            self.inOrderTraverse(node.lchild)
            print node.data,
            self.inOrderTraverse(node.rchild)
 
    # 后序遍历
    def postOrderTraverse(self, node):
        if node is not None:
            self.postOrderTraverse(node.lchild)
            self.postOrderTraverse(node.rchild)
            print node.data,
 
a = [49, 38, 65, 97, 60, 76, 13, 27, 5, 1]
bst = BST(a)  # 创建二叉查找树
bst.inOrderTraverse(bst.root)  # 中序遍历
 
bst.delete(bst.root, 49)
print
bst.inOrderTraverse(bst.root)

4. 练习

98. 验证二查搜索树

[https://leetcode-cn.com/problems/validate-binary-search-tree/]
题目描述
给定一个二叉树,判断其是否是一个有效的二叉搜索树。

假设一个二叉搜索树具有如下特征:

节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
在这里插入图片描述

代码实现

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def isValidBST(self, root: TreeNode,min=None,max=None) -> bool:
        if root==None:
            return True
        if min!=None and min>=root.val:
            return False
        if max!=None and max<=root.val:
            return False
        return self.isValidBST(root.left,min=min,max=root.val) and self.isValidBST(root.right,min=root.val,max=max)
102. 二叉树的层次遍历

[https://leetcode-cn.com/problems/binary-tree-level-order-traversal/submissions/]
题目描述
给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。
在这里插入图片描述

代码实现

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        res = []
        if not root:
            return res
        temp = [root]
        while temp:
            cur = []
            next_temp = []
            for node in temp:
                cur.append(node.val)
                if node.left:
                    next_temp.append(node.left)
                if node.right:
                    next_temp.append(node.right)
            res.append(cur)
            temp = next_temp
        return res
107. 二叉树的层次遍历 II

[https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii/]
题目描述
给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
在这里插入图片描述

代码实现

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
        if root == None: 
            return []
        stack = [root]
        res = []
        while len(stack) != 0:
            tmp = []
            res_each = []
            for i in stack:
                res_each.append(i.val)
                if i.left != None:
                    tmp.append(i.left)
                if i.right != None:
                    tmp.append(i.right)
            stack = tmp
            res.insert(0,res_each)
        return res
226. Invert Binary Tree(翻转二叉树)

[https://leetcode-cn.com/problems/invert-binary-tree/]
题目描述
给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/838017ddae77a095738dcbbbf1f3e443.png)

代码实现

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if root==None:
            return None
        root.left,root.right=root.right, root.left
        self.invertTree(root.left)
        self.invertTree(root.right)
        return root
104. Maximum Depth of Binary Tree(二叉树的最大深度)

[https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/submissions/]
题目描述
给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

在这里插入图片描述
代码实现

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        # 当当前根为空时返回:空树
        if root is None:
            return 0
        # 当还能继续往下钻
        return max(self.maxDepth(root.left), self.maxDepth(root.right))+1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值