zoukankan      html  css  js  c++  java
  • 二叉树

    树(tree)是n(n>=0)个节点的有限集。当n=0时,称为空树。

    在任意一个非空树中,有如下特点:

    1.有且仅有一个特点的称为根的节点
    2.当n>1时,其余节点可分为m个互不相交的有限集,每一个集合本身又是一个树,并称为根的子树。
    关键字:根节点;叶子节点;父节点;孩子节点;兄弟节点

    二叉树:

    左孩子结点,右孩子结点

    满二叉树:

    一个二叉树的所有非叶子节点都存在左孩子和右孩子,并且所有叶子节点都在同一层级上,那么这个树就是满二叉树

    完全二叉树:

    定义太复杂了,记特点吧:满二叉树一定是完全二叉树,完全二叉树不一定是满二叉树;满二叉树要求所有节点分支都是满的
    而完全二叉树只要保证最后一个节点之前的节点都齐全即可(也就是说,最后一个非叶子节点可以没有右孩子节点,有没有左孩子节点它都是完全二叉树)

    二叉树的链式存储结构

    二叉树中的一个节点最多可以指向左右两个孩子节点,所以二叉树节点包含3部分
    1.存储数据的data变量
    2.指向左孩子的left指针
    3.指向右孩子的right指针

    二叉树的数组存储

    使用数组存储时,会按层级顺序把二叉树的节点放到数组中对应的位置上。
    如果某一个节点的左孩子或右孩子空缺,则数组的相应位置也空出来
    这样可以更方便的在数组中定位二叉树的孩子节点和父节点
    假设一个父节点的下标是parent1,那么它的左孩子节点的下标就是2*parent+1;
    右孩子节点的下标就是2*parent+2
    反过来,假设一个左孩子节点的下标是leftChild,那么他的父节点下标就是(leftChild-1)/2

    二叉树的应用:

    查找操作和维持相对顺序

    1.查找

    二叉查找树在二叉树的基础上增加了以下几个条件:
    1.1如果左子树不为空,则左子树上所有节点的值均小于根节点的值
    1.2如果右子树不为空,则右子树上所有节点的值均大于根节点的值
    1.3左子树、右子树也都是二叉查找树
    原则是左子树的值小于根节点的值,右子树的值大于根节点的值
    对于一个节点分布相对均衡的二叉查找树来说,如果节点总数是n,那么搜索节点的时间复杂的就是O(logn),和树的深度是一样的

    2.维持相对顺序

    二叉查找树要求左子树节点的值小于父节点的值,右子树节点的值大于父节点的值,正是这样保证了二叉树的有序性

    二叉查找树又称二叉排序树,需要插入的元素须遵守二叉排序数的原则,如从根节点插入,最终的位置需从根节点到左孩子节点或右孩子节点(原则是左子树的值小于根节点的值,右子树的值大于根节点的值)
    但却有个问题,若插入的都是比根节点小的元素,那岂不都插入到左孩子节点中去么,所以这就涉及到二叉树的自平衡,如红黑树、AVL树、树堆等。
    除了二叉查找树以外,二叉堆也维持着相对的顺序,只要求父节点的值比他的左右孩子的值都大。

    遍历二叉树,二叉树是非线性数据结构

    遍历时需要把非线性关联的节点转化成一个线性的序列。以不同的方式来遍历,遍历出的序列顺序也不同

    二叉树的遍历分为3种(深度优先遍历)

    1.前序遍历:根节点-->左子树-->右子树
    2.中序遍历:左子树-->根节点-->右子树
    3.后续遍历:左子树-->右子树-->根节点

    二叉树的层序遍历(也称广度优先遍历)

    如果说深度优先遍历是在一个方向上"一头扎到底",那么广度优先遍历则恰恰相反;现在各个方向上各走一步,再在各个方向上
    走出第2步、第3步.....一直到各个方向全部走完。
    层序遍历顾名思义就是二叉树按照从根节点到叶子节点的层次关系,一层一层横向遍历各个节点
    可是,二叉树同一层次的节点之间是没有直接关联的,这时需要借助一个数据结构来辅助工作,这个数据结构就是队列

    二叉树的三种遍历方法

    class TreeNode:
        def __init__(self, data):
            self.data = data
            self.left = None
            self.right = None
    
    
    def create_binary_tree(input_list=[]):
        """
        构建二叉树
        :param input_list: 输入数列
        
        """
        if input_list is None or len(input_list) == 0:
            return None
        data = input_list.pop(0)
        if data is None:
            return None
        node = TreeNode(data)
        node.left = create_binary_tree(input_list)
        node.right = create_binary_tree(input_list)
        return node
    
    
    def pre_order_traversal(node):
        """
        前序遍历
        :param node: 二叉树节点
        """
        if node is None:
            return
        print(node.data)
        pre_order_traversal(node.left)
        pre_order_traversal(node.right)
        return node
    
    
    def in_order_traversal(node):
        """
        中序遍历
        :param node: 二叉树节点
        """
        if node is None:
            return
        in_order_traversal(node.left)
        print(node.data)
        in_order_traversal(node.right)
        return node
    
    
    def post_order_traversal(node):
        """
        后序遍历
        :param node: 二叉树节点
        """
        if node is None:
            return
        post_order_traversal(node.left)
        post_order_traversal(node.right)
        print(node.data)
        return node
    
    # 这里吧一个线性的链表转化为非线性的二叉树
    my_input_list = list([3, 2, 9, None, None, 10, None, None, 8, None, 4])
    root = create_binary_tree(my_input_list)
    print("前序遍历:")
    pre_order_traversal(root)
    print("中序遍历:")
    in_order_traversal(root)
    print("后序遍历:")
    post_order_traversal(root)
    

    二叉树非递归前序遍历

    采用的是栈

    class TreeNode:
        def __init__(self, data):
            self.data = data
            self.left = None
            self.right = None
    
    
    def create_binary_tree(input_list=[]):
        if input_list is None or len(input_list) == 0:
            return None
        data = input_list.pop(0)
        if data is None:
            return None
        node = TreeNode(data)
        node.left = create_binary_tree(input_list)
        node.right = create_binary_tree(input_list)
        return node
    
    # 二叉树非递归前序遍历
    def pre_order_traversal_with_stack(node):
        stack = []
        while node is not None or len(stack) > 0:
            while node is not None:
                print(node.data)
                stack.append(node)
                node = node.left
            if len(stack) > 0:
                node = stack.pop()
                node = node.right
    
    
    my_input_list = list([3, 2, 9, None, None, 10, None, None, 8, None, 4])
    root = create_binary_tree(my_input_list)
    print("前序遍历:")
    pre_order_traversal_with_stack(root)
    

    二叉树的层序遍历(广度优先遍历)

    采用的是队列

    from queue import Queue
    
    
    
    def level_order_traversal(node):
        queue = Queue()
        queue.put(node)
        while not queue.empty():
            node = queue.get()
            print(node.data)
            if node.left is not None:
                queue.put(node.left)
            if node.right is not None:
                queue.put(node.right)
    
    
    def create_binary_tree(input_list=[]):
        if input_list is None or len(input_list) == 0:
            return None
        data = input_list.pop(0)
        if data is None:
            return None
        node = TreeNode(data)
        node.left = create_binary_tree(input_list)
        node.right = create_binary_tree(input_list)
        return node
    
    
    class TreeNode:
        def __init__(self, data):
            self.data = data
            self.left = None
            self.right = None
    
    
    my_input_list = list([3, 2, 9, None, None, 10, None, None, 8, None, 4])
    root = create_binary_tree(my_input_list)
    print("层序遍历:")
    level_order_traversal(root)
    
    努力拼搏吧,不要害怕,不要去规划,不要迷茫。但你一定要在路上一直的走下去,尽管可能停滞不前,但也要走。
  • 相关阅读:
    Mysql存储过程和函数
    python反编译chm文件并生成pdf文件
    python转换html到pdf文件
    python获取系统开机时间
    OpenSL ES: 利用OpenSL ES实现录音功能
    android: 根据文件uri 获取文件名
    Java: InputStream转化为byte数组
    Linux: 查看二进制文件
    Vim: 回到上次编辑的位置
    LayoutInflate: Avoid passing null as the view root
  • 原文地址:https://www.cnblogs.com/wkhzwmr/p/15248375.html
Copyright © 2011-2022 走看看