美文网首页算法数据结构和算法分析
超简单二叉树python实现及二叉树排序

超简单二叉树python实现及二叉树排序

作者: 京酱玫瑰 | 来源:发表于2019-09-30 14:31 被阅读0次

    二叉树其实直观理解起来还算比较简单,它是一个树结构,也就是层级结构,每一层每一个父节点最多有两个子节点。二叉树用来搜索效果不错,因为只要保证左节点比父节点小,右节点比父节点大,那么搜索下来时间复杂度其实就是很理想的O(logn)。

    但是对于一个python新手来说,二叉树也是比较难实现的,因为按理说树结构其实应该是一种“链表”,但是python里面似乎可能好像没有这种结构,Java是有的(有人开始骂python是一门很low的语言了)……所以一开始我理解起来还很困难!这个怎么能把树上的每个节点串起来啊,怎么表示关系啊,然后我去刷stackoverflow,还真的慢慢地理解了它(的基础)。

    1. 建立节点

    如上文所述,二叉树的结构就是每一个父节点都有不超过两个子节点。那么对于二叉树的每个点建一个类,这个类中规定三个属性:节点自身的值value,节点的左子节点值left,节点的右子节点值right。对于每一个点而言,在初始化的时候都把一个值赋给它自己,同时左右子节点置为空。这个很好理解吧?叶子节点的左右子节点就会一直为空了,但是

    代码:

    class TreeNode(object):
        def __init__(self,value):
            self.value = value
            self.left = None
            self.right = None
    

    2. 建立搜索树

    现在我们有了点,看起来很简单,但是该怎么把树建起来呢?

    二叉树建树其实就像上面说的,是一个很简单明确的过程,首先需要一个根节点,然后每一次新的节点过来,就跟根节点比较,比它小就作为左子节点,比它大就作为右子节点,然后依次跟下一层比较,直到自己成为叶子节点停止。

    算法的要点是利用递归算法 recursion,说实话靠我自己想可能还是太难太抽象了点。但是如果你要去领会它的意思,做得也就是这件事:

    class BinaryTree(object):
        def insert(self,root,value):
            if root is None:
                return value
            if value.value < root.value:
                root.left = self.insert(root.left,value)
            else:
                root.right = self.insert(root.right, value)
            return root
    

    我们定义了一个新的类 二叉树,这个类里面只有一个insert方法,就是插入一个新的数据到已生成的树中。这个方法的记忆点有两块:

    1.输入参数:

    此处的参数应该是已生成的树节点,和准备加入的新节点,这两者的类型都需要是刚刚定义的带有左右子节点属性的类

    2.递归,采用三个条件判断:

    如果当前节点为空就返回新的节点;如果当前节点不为空且比新的节点值大,那么就递归地判断当前节点的左子节点和新节点的关系,直到当前节点为空;比新的节点小就递归地判断当前节点的左子节点和新节点的关系,直到当前节点为空返回。

    3. 生成二叉搜索树:

    那么下面我们就用一个循环语句来生成一棵二叉搜索树吧。

    root = Node(5)
    tree = BinaryTree()
    
    for i in [2,11,7,3,9,8,4,6,1]:
        tree.insert(root,Node(i))
    

    现在基本上大功告成了!当你兴奋地敲下run之后,当当当当——

    程序运行完,啥也没显示,就完了。

    那是因为我们没有把树“遍历”地展示出来,python有一个二叉树库 binarytree,可以用pip安装,允许你打印出树的结构,可以用非常直观的方式来构建二叉树,看看人家的示例:

    >>> from binarytree import Node
    >>> root = Node(3)
    >>> root.left = Node(2)
    >>> root.right = Node(7)
    >>> root.left.left = Node(4)
    >>> root.left.right = Node(1)
    >>> print(root)
    
        __3
       /   \
      2     7
     / \
    4   1
    
    

    4. 二叉树的三种遍历算法及排序

    当我们已经有一个二叉树的时候,有哪几种方式来遍历它呢?

    这是一个面试常见考点,相信很多小伙伴脑子里已经蹦出了答案:前序遍历,中序遍历,后序遍历

    那么哪种遍历方法可以使二叉树输出有序呢?

    中序遍历

    在说到二叉树遍历的前序,中序和后序的时候,需要牢牢记住,这里的前,中,后的顺序,都是相对于节点本身而言的。所以“前序遍历”实际上的意思是:把遍历我这个父节点先放到前面,然后再左子节点,然后再右子节点,一直要保证这个顺序。中序遍历就是把遍历父节点放在中间去进行,先左子节点,然后再右子节点,子节点的遍历需要注意的是这个过程也是递归的。后序遍历呢,就是先左子节点,然后右子节点,最后再遍历父节点。

    所以,自然,由于二叉树本身生成的时候的特性,再遍历的时候如果采用中序,就能够保证整个输出是从小到大有序的了。

    所以我们定义三个新的函数来表示这三种遍历方法:

    # 前序遍历
    def pre_order_print(node):
        # self -- left -- right
        print(node.value,end=' ')
        if node.left:
            pre_order_print(node.left)
        if node.right:
            pre_order_print(node.right)
    # 中序遍历     
    def mid_order_print(node):
        # left --self -- right
        if node.left:
            mid_order_print(node.left)
        print(node.value,end=' ')
        if node.right:
            mid_order_print(node.right)
    # 后序遍历     
    def after_order_print(node):
        # left-- right--self
        if node.left:
            after_order_print(node.left)
        if node.right:
            after_order_print(node.right)
        print(node.value, end=' ')
    
    
    1. 完整的程序
    class Node(object):
        def __init__(self,value):
            self.value = value
            self.left = None
            self.right = None
    
    class BinaryTree(object):
        def insert(self,root,value):
            if root is None:
                return value
            if value.value < root.value:
                root.left = self.insert(root.left,value)
            else:
                root.right = self.insert(root.right, value)
    
            return root
    
    def pre_order_print(node):
        # self -- left -- right
        print(node.value,end=' ')
        if node.left:
            pre_order_print(node.left)
        if node.right:
            pre_order_print(node.right)
            
    def mid_order_print(node):
        # mid --self -- right
        if node.left:
            mid_order_print(node.left)
        print(node.value,end=' ')
        if node.right:
            mid_order_print(node.right)
    
    def after_order_print(node):
        # left-- right--self
        if node.left:
            after_order_print(node.left)
        if node.right:
            after_order_print(node.right)
        print(node.value, end=' ')
    
    root = Node(5)
    
    tree = BinaryTree()
    
    for i in [2,11,7,3,9,8,4,6,1]:
        tree.insert(root,Node(i))
    mid_order_print(root)
    

    这样输出的结果就是有序的了。

    相关文章

      网友评论

        本文标题:超简单二叉树python实现及二叉树排序

        本文链接:https://www.haomeiwen.com/subject/hdxjuctx.html