算法-Python2.7实现平衡二叉树中序遍历(in-order traversal of the AVL tree)

# coding=UTF-8
import numpy as np
class Node:
    def __init__(self):
        self.left_children = None
        self.left_height = 0
        self.right_children = None
        self.right_height = 0
        self.value = None
class tree:
    def __init__(self):
        self.root = False
        self.front_list = []
        self.middle_list = []
        self.after_list = []
    # 生成二叉树
    def create_tree(self,n=0,l=[]):
        if l == []:
            return
        if n > len(l)-1:
            return
        node = Node()
        node.value = l[n]
        if not self.root:
           self.root = node
           self.list = l
        else:
            self.add(self.root,node)
        self.create_tree(n+1,l)
    # 添加节点
    def add(self,parent,new_node):
        if new_node.value > parent.value:
            # 插入值比父亲值大,所以在父节点右边
            if parent.right_children == None:
                parent.right_children = new_node
                # 新插入节点的父亲节点的高度值为1,也就是子高度值0+1
                parent.right_height = 1
                # 插入值后 从下到上更新节点的height
            else:
                self.add(parent.right_children,new_node)
                # 父亲节点的右高度等于右孩子,左右高度中较大的值 + 1
                parent.right_height = max(parent.right_children.right_height, parent.right_children.left_height) + 1
                # ======= 此处开始判断平衡二叉树=======
                # 右边高度大于左边高度 属于右偏
                if parent.right_height - parent.left_height >= 2:
                    self.right_avertence(parent)
        else:
            # 插入值比父亲值小,所以在父节点左边
            if parent.left_children == None:
                parent.left_children = new_node
                parent.left_height = 1
            else:
                self.add(parent.left_children,new_node)
                parent.left_height = max(parent.left_children.right_height, parent.left_children.left_height) + 1
                # ======= 此处开始判断平衡二叉树=======
                # 左边高度大于右边高度 属于左偏
                if parent.left_height - parent.right_height >= 2:
                    self.left_avertence(parent)
    # 更新当前节点下的所有节点的高度
    def update_height(self,node):
        # 初始化节点高度值为0
        node.left_height = 0
        node.right_height = 0
        # 是否到最底层的一个
        if node.left_children == None and node.right_children == None:
            return
        else:
            if node.left_children:
                self.update_height(node.left_children)
                # 当前节点的高度等于左右子节点高度的较大值 + 1
                node.left_height = max(node.left_children.left_height,node.left_children.right_height) + 1
            if node.right_children:
                self.update_height(node.right_children)
                # 当前节点的高度等于左右子节点高度的较大值 + 1
                node.right_height = max(node.right_children.left_height, node.right_children.right_height) + 1
            # 检查是否仍有不平衡
            if node.left_height - node.right_height >= 2:
                self.left_avertence(node)
            elif node.left_height - node.right_height <= -2:
                self.right_avertence(node)
    def right_avertence(self,node):
        # 右偏 就将当前节点的最左节点做父亲
        new_code = Node()
        new_code.value = node.value
        new_code.left_children = node.left_children
        best_left = self.best_left_right(node.right_children)
        v = node.value
        # 返回的对象本身,
        if best_left == node.right_children and best_left.left_children == None:
            # 说明当前节点没有有节点
            node.value = best_left.value
            node.right_children = best_left.right_children
        else:
            node.value = best_left.left_children.value
            best_left.left_children = best_left.left_children.right_children
        node.left_children = new_code
        self.update_height(node)

    # 处理左偏情况
    def left_avertence(self,node):
        new_code = Node()
        new_code.value = node.value
        new_code.right_children = node.right_children
        best_right = self.best_left_right(node.left_children,1)
        v = node.value
        # 返回的对象本身,
        if best_right == node.left_children and best_right.right_children == None:
            # 说明当前节点没有有节点
            node.value = best_right.value
            node.left_children = best_right.left_children
        else:
            node.value = best_right.right_children.value
            best_right.right_children = best_right.right_children.left_children
        node.right_children = new_code
        self.update_height(node)
    # 返回node节点最左(右)子孙的父级
    def best_left_right(self,node,type=0):
        # type=0 默认找最左子孙
        if type == 0:
            if node.left_children == None:
                return node
            elif node.left_children.left_children == None:
                return node
            else:
                return self.best_left_right(node.left_children,type)
        else:
            if node.right_children == None:
                return node
            elif node.right_children.right_children == None:
                return node
            else:
                return self.best_left_right(node.right_children,type)
    # 中序(先左再中最后右)
    def middle(self,node=None):
        if node == None:
            node = self.root
        # 先判断左枝
        if not node.left_children == None:
            self.middle(node.left_children)
        # 输出当前节点
        self.middle_list.append(node.value)
        # 再判断右枝
        if not node.right_children == None:
            self.middle(node.right_children)
        return self.middle_list
if __name__ == "__main__":
    npyArray = [41,20,65,11,29,50,26,23]
    avl = tree()
    avl.create_tree(0,npyArray)
    result = avl.middle()
    print 'Inorder traversal:', result

 

输出结果:Inorder traversal: [11, 20, 23, 26, 29, 41, 50, 65]

 

如果对你有帮助的话,给我点个赞,让我分享一些技术的时候更有动力。

另外我建了一个公众号,会不时分享前端的一些技术,或者遇到的难题和解决办法,欢迎大家关注。

搜索:钱端工程师       或        Money-end-engineer      或       扫描下方图片

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值