二叉树创建,添加功能优化(比一般的要快很多)+4种遍历二叉树方法

事先声明:  此文章讲解二叉树基础,当然有一定基础的大佬也可以参考参考优化后的添加方法,对于元素比较多的元素可以大幅度减少添加时遍历的时间,添加n个元素时间复杂度为O(n),每次单个添加一个元素时间复杂度为O(1),当然了,肯定是空间换时间的算法了,普通的算法每次用完栈会清空,优化后的则会保存未被pop的元素供以下次接着这个节点遍历,空间消耗的多少取决于最后一层的元素个数,假设这个二叉树达到了k层,则这个用于储存的栈的长度不会超过2的(k+1)次方个,但是对于时间上的优化效果还是不错的,每次添加元素消耗时间相对于一前的O(n),现在的O(1)是不是香多了呢?
 

#创建树对象
class tree:
    def __init__(self,item=None):
        self.stack = [self]  # stack用于后面二叉树添加元素,初始化栈,把stack当作self的属性,保留上一次查找后的剩余的数据
        self.root=item
        self.lchild=None
        self.rchild=None

    class node:                           #创建树的节点类
        def __init__(self, item=None):
            self.item = item
            self.lchild = None  # 初始化节点的左孩子
            self.rchild = None  # 初始化节点的右孩子















    def add(self,item):         #创建add方法按照二叉树的规定添加元素

        if self.root==None:     #根节点无元素时
            self.root=item
            return

        #一直遍历栈里的节点,直到找到空的位置,把元素添加进去,然后用return终止进程
        while(self.stack):
            curnode=self.stack[0]     #出栈,但是我并没有pop出来,原因是我先判断这个节点有没有满,满了再pop,当下一次再调用add时,不用重新检索
            #如果左节点无元素,则添加在此节点
            if not curnode.lchild:
                curnode.lchild=self.node(item)
                                         #因为没有抛出此节点,所以下一次add还会判断stack最开始的那个元素的左孩子,所以暂时不用在栈里添加左孩子
                return
            #如果右孩子也存在,则应该pop此节点,然后还要添加此节点的左右孩子
            elif curnode.rchild:
                '''此时就已经可以判断该节点左,右孩子都存在,就可以pop了,同时也要在栈里添加左右孩子'''
                self.stack.pop(0)
                self.stack.append(curnode.lchild)
                self.stack.append(curnode.rchild)
                return
            #最后一种情况,有左孩子,没右孩子
            else:
                # 和上一种情况类似,因为既然没有有孩子,则可以把元素添加到此位置,然后此节点就满了,满了就应该pop,然后将其左孩子和右孩子添加到stack里面
                curnode.rchild = self.node(item)
                self.stack.pop(0)
                self.stack.append(curnode.lchild)
                self.stack.append(curnode.rchild)
                return


a=tree(1)
a.add(2)
a.add(3)
a.add(4)
a.add(5)
a.add(6)
a.add(7)
# print(a.lchild.lchild.item)
for i in a.stack:
    print(i.item)

添加了哪些元素添加元素后stack中有哪些元素
1self
1,2self
1,2,32    3
1,2,3,42    3
1,2,3,4,53    4     5
1,2,3,4,5,63    4     5
添加1234567会是什么,答案在后面~~

当然这种优化对于储存少量的树,层数多的树比较好,然而对于树太多,然而层数少,效果就不太明显了,所以该怎么选还要看情况而定;

接下来讲讲4种遍历了;

#既然是基础,那就要用最简单的方法来遍历了(使用递归)

如果对于递归不熟悉,请出门左转,看看汉诺塔是怎么解决的

   

def preorder_travel(self, node):  # 先序搜索
    if node == None:
        return
    print(node.ele)
    self.preorder_travel(node.lchild)
    self.preorder_travel(node.rchild)

         中序:

                 

 

def inorder_travel(self, node):  # 中序搜索
    if node == None:
        return
    self.inorder_travel(node.lchild)
    print(node.ele)
    self.inorder_travel(node.rchild)

后序:

def lastorder_travel(self, node):  # 后序排列
    if node == None:
        return
    self.lastorder_travel(node.lchild)
    self.lastorder_travel(node.rchild)
    print(node.ele)

#最后层遍历

顾名思义,就是一层一层输出,从左到右,1 2 3 4 5 6 7

def chenci_travel(self, node):  # 层次排列
    queue = [node]
    while queue:
        node = queue.pop(0)
        if node == None:
            print(' no elements')
            return
        print(node.ele)
        if node.lchild != None:
            queue.append(node.lchild)
        if node.rchild != None:
            queue.append(node.rchild)

对于之前没给的答案是4 5 6 7,理解其原理就十分简单了!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值