事先声明: 此文章讲解二叉树基础,当然有一定基础的大佬也可以参考参考优化后的添加方法,对于元素比较多的元素可以大幅度减少添加时遍历的时间,添加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中有哪些元素 |
---|---|
1 | self |
1,2 | self |
1,2,3 | 2 3 |
1,2,3,4 | 2 3 |
1,2,3,4,5 | 3 4 5 |
1,2,3,4,5,6 | 3 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,理解其原理就十分简单了!