python 平衡二叉树实现代码示例

平衡二叉树:

在上一节二叉树的基础上我们实现,如何将生成平衡的二叉树

所谓平衡二叉树:

我自己定义就是:任何一个节点的左高度和右高度的差的绝对值都小于2

如图所示,此时a的左高度等于3,有高度等于1,差值为2,属于不平衡中的左偏

  

此时的处理办法就是:

将不平衡的元素的左枝的最右节点变为当前节点,

此时分两种情况:

一、左枝有最右节点

将最右节点的左枝赋予其父节点的右枝

二、左枝没有最右节点,

直接将左枝节点做父级节点,父级节点做其右枝

      

如图所示,图更清楚些。

可能会有疑问,为什么这样变换?

假定a左偏,就需要一个比a小的最少一个值d(因为d唯一 一个是比a小,而且比a的左枝所有数都大的值)做父集结点,a做d的右枝,这样在最上面的d节点就平衡了。

我们可以反证一下:

如果不是d是另一个数假设为h,此时h做父节点,a做父节点的右节点

因为a在h右边,所以 a > h

因为b,e,d,f都是h的左枝,所以 h>d>b>e>f

所以 a>h>d>b>e>f

所以在不加入新节点的情况下,就只能是d    

左偏和右偏是一样的,可以完全镜像过来就ok了

处理了所有节点 的左偏和右偏使整个二叉树平衡,这就是平衡二叉树的基本思想

代码实现:

# -*- coding:utf-8 -*-
# 日期:2018/6/12 8:37
# Author:小鼠标

# 节点对象
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 == []:
      print("传入的列表为空")
      return
    if n > len(l)-1:
      print("二叉树生成")
      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 front(self,node=None):
    if node == None:
      self.front_list = []
      node = self.root
    # 输出当前节点
    self.front_list.append(node.value)
    # 先判断左枝
    if not node.left_children == None:
      self.front(node.left_children)
    # 再判断右枝
    if not node.right_children == None:
      self.front(node.right_children)
    # 返回最终结果
    return self.front_list
  # 中序(先左再中最后右)
  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
  # 后序(先左再右最后中)
  def after(self,node=None):
    if node == None:
      node = self.root
    # 先判断左枝
    if not node.left_children == None:
      self.after(node.left_children)
    # 再判断右枝
    if not node.right_children == None:
      self.after(node.right_children)
    self.after_list.append(node.value)
    return self.after_list
  # 节点删除
  def del_node(self,v,node=None):
    if node == None:
      node = self.root
      # 删除根节点
      if node.value == v:
        self.del_root(self.root)
        return
    # 删除当前节点的左节点
    if node.left_children:
      if node.left_children.value == v:
        self.del_left(node)
        return
    # 删除当前节点的右节点
    if node.right_children:
      if node.right_children.value == v:
        self.del_right(node)
        return
    if v > node.value:
      if node.right_children:
        self.del_node(v, node.right_children)
      else:
        print("删除的元素不存在")
    else:
      if node.left_children:
        self.del_node(v, node.left_children)
      else:
        print("删除的元素不存在")
  #删除当前节点的右节点
  def del_right(self,node):
    # 情况1 删除节点没有右枝
    if node.right_children.right_children == None:
      node.right_children = node.right_children.left_children
    else:
      best_left = self.best_left_right(node.right_children.right_children)
      # 表示右枝最左孙就是右枝本身
      if best_left == node.right_children.right_children and best_left.left_children == None:
        node.right_children.value = best_left.value
        node.right_children.right_children = best_left.right_children
      else:
        node.right_children.value = best_left.left_children.value
        best_left.left_children = best_left.left_children.right_children
  # 删除当前节点的左节点
  def del_left(self,node):
    # 情况1 删除节点没有右枝
    if node.left_children.right_children == None:
      node.left_children = node.left_children.left_children
    else:
      best_left = self.best_left_right(node.left_children.right_children)
      # 表示右枝最左子孙就是右枝本身
      if best_left == node.left_children.right_children and best_left.left_children == None:
        node.left_children.value = best_left.value
        node.left_children.right_children = best_left.right_children
      else:
        node.left_children.value = best_left.left_children.value
        best_left.left_children = best_left.left_children.right_children
  # 删除根节点
  def del_root(self,node):
    if node.right_children == None:
      if node.left_children == None:
        node.value = None
      else:
        self.root = node.left_children
    else:
      best_left = self.best_left_right(node.right_children)
      # 表示右枝最左子孙就是右枝本身
      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

  # 搜索
  def search(self,v,node=None):
    if node == None:
      node = self.root
    if node.value == v:
      return True
    if v > node.value:
      if not node.right_children == None:
        return self.search(v, node.right_children)
    else:
      if not node.left_children == None:
        return self.search(v, node.left_children)
    return False
if __name__ == '__main__':
  # 需要建立二叉树的列表
  list = [4, 6, 3, 1, 7, 9, 8, 5, 2]
  t = tree()
  t.create_tree(0,list)
  res = t.front()
  print('前序', res)

执行结果:

前序 [4, 2, 1, 3, 7, 6, 5, 9, 8]

通过前序可以画出二叉树

完美,哈哈。

这是我钻了两天才写出的代码,哈哈,努力还是有回报的,加油。

下一步就是代码优化了

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Python定义二叉树及4种遍历方法实例详解

    本文实例讲述了Python定义二叉树及4种遍历方法.分享给大家供大家参考,具体如下: Python & BinaryTree 1. BinaryTree (二叉树) 二叉树是有限个元素的集合,该集合或者为空.或者有一个称为根节点(root)的元素及两个互不相交的.分别被称为左子树和右子树的二叉树组成. 二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒. 二叉树的第i层至多有2^{i-1}个结点 深度为k的二叉树至多有2^k-1个结点: 对任何一棵二叉

  • Python编程把二叉树打印成多行代码

    题目描述 从上到下按层打印二叉树,同一层结点从左至右输出.每一层输出一行. 思路: 1.把每层节点的val值用list存好 2.把每层节点存好: ①计算当层节点的个数,这样就保证下一步每层的结点都被pop光 ②然后依次弹出从左到右的每个节点,然后在list中加入该节点对应的左结点.右节点(如果存在的话) 代码如下: class TreeNode(): def __init__(self,x): self.val = x self.left = None self.right = None def

  • Python二叉树定义与遍历方法实例分析

    本文实例讲述了Python二叉树定义与遍历方法.分享给大家供大家参考,具体如下: 二叉树基本概述: 二叉树是有限个元素的几个,如果为空则为空二叉树,或者有一个结点称之为根节点,分列根节点两侧的为二叉树的左右子节点,二叉树有如下的性质: 1. 二叉树的每个结点不存在度大于2的结点 2. 二叉树的第i层至多有2^{i-1}个结点 3. 深度为k的二叉树至多有2^k - 1个结点 4. 二叉树中,度为0的结点数N0比度为2的结点数N2大1,即存在N2 + 1 = N0 Python代码: #codin

  • python使用递归的方式建立二叉树

    树和图的数据结构,就很有意思啦. # coding = utf-8 class BinaryTree: def __init__(self, root_obj): self.key = root_obj self.left_child = None self.right_child = None def insert_left(self, new_node): node = BinaryTree(new_node) if self.left_child is None: self.left_ch

  • python3实现二叉树的遍历与递归算法解析(小结)

    1.二叉树的三种遍历方式 二叉树有三种遍历方式:先序遍历,中序遍历,后续遍历 即:先中后指的是访问根节点的顺序 eg:先序 根左右 中序 左根右 后序 左右根 遍历总体思路:将树分成最小的子树,然后按照顺序输出 1.1 先序遍历 a 先访问根节点 b 访问左节点 c 访问右节点 a(b ( d ( h ) )( e ( i ) ))( c ( f )( g )) -- abdheicfg 1.2 中序遍历 a 先访问左节点 b 访问根节点 c 访问右节点 ( ( ( h ) d ) b ( (

  • Python二叉树的镜像转换实现方法示例

    本文实例讲述了Python二叉树的镜像转换实现方法.分享给大家供大家参考,具体如下: 问题描述 操作给定的二叉树,将其变换为源二叉树的镜像. 思路描述 1. 代码比文字更直观 2. 文字描述:新建一个二叉树,利用递归法,将源二叉树上的左节点赋值到新二叉树的右节点,将源二叉树上的右节点赋值到新二叉树的左节点. Python代码 # 方式1:生成新的镜像二叉树 def getMirrorBST(self, root): if root == None: return newTree = treeNo

  • Python实现重建二叉树的三种方法详解

    本文实例讲述了Python实现重建二叉树的三种方法.分享给大家供大家参考,具体如下: 学习算法中,探寻重建二叉树的方法: 用input 前序遍历顺序输入字符重建 前序遍历顺序字符串递归解析重建 前序遍历顺序字符串堆栈解析重建 如果懒得去看后面的内容,可以直接点击此处本站下载完整实例代码. 思路 学习算法中,python 算法方面的资料相对较少,二叉树解析重建更少,只能摸着石头过河. 通过不同方式遍历二叉树,可以得出不同节点的排序.那么,在已知节点排序的前提下,通过某种遍历方式,可以将排序进行解析

  • Python 二叉树的层序建立与三种遍历实现详解

    前言 二叉树(Binary Tree)时数据结构中一个非常重要的结构,其具有....(此处省略好多字)....等的优良特点. 之前在刷LeetCode的时候把有关树的题目全部跳过了,(ORZ:我这种连数据结构都不会的人刷j8Leetcode啊!!!) 所以 !!!敲黑板了!!!今天我就在B站看了数据结构中关于树的内容后,又用我浅薄的Python大法来实现一些树的建立和遍历. 关于树的建立我觉得层序建立对于使用者来说最为直观,输入很好写.(好吧,我是看LeetCode中的树输入都是采用层序输入觉得

  • 基于python二叉树的构造和打印例子

    写在最前面: 带你从最简单的二叉树构造开始,深入理解二叉树的数据结构,ps:不会数据结构的程序猿只能是三流的 首先,我们构造一个二叉树 这是最标准,也是最简单的二叉树构造方法 ''' 树的构建: 3 9 20 15 7 ''' class Tree(): '树的实现' def __init__(self,data,left = 0,right = 0): self.left = left self.right = right self.data = data def __str__(self):

  • Python简单定义与使用二叉树示例

    本文实例讲述了Python简单定义与使用二叉树的方法.分享给大家供大家参考,具体如下: class BinaryTree: def __init__(self,rootObj): self.root = rootObj self.leftChild = None self.rightChild = None def insertLeft(self,newNode): if self.leftChild == None: self.leftChild = BinaryTree(newNode) e

随机推荐