算法数据结构和算法分析

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

2019-09-30  本文已影响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)

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

上一篇下一篇

猜你喜欢

热点阅读