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


Posted in Python onJuly 07, 2018

平衡二叉树:

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

所谓平衡二叉树:

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

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

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

此时的处理办法就是:

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

此时分两种情况:

一、左枝有最右节点

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

二、左枝没有最右节点,

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

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

如图所示,图更清楚些。

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

假定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]

通过前序可以画出二叉树

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

完美,哈哈。

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

下一步就是代码优化了

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

Python 相关文章推荐
使用python实现strcmp函数功能示例
Mar 25 Python
django接入新浪微博OAuth的方法
Jun 29 Python
Python中str is not callable问题详解及解决办法
Feb 10 Python
Python切片索引用法示例
May 15 Python
python 读取视频,处理后,实时计算帧数fps的方法
Jul 10 Python
python+selenium实现自动化百度搜索关键词
Jun 03 Python
python 多线程对post请求服务器测试并发的方法
Jun 13 Python
python 批量解压压缩文件的实例代码
Jun 27 Python
python脚本实现音频m4a格式转成MP3格式的实例代码
Oct 09 Python
python 递归调用返回None的问题及解决方法
Mar 16 Python
Python requests模块cookie实例解析
Apr 14 Python
Python logging模块原理解析及应用
Aug 13 Python
详解python异步编程之asyncio(百万并发)
Jul 07 #Python
基于Python开发chrome插件的方法分析
Jul 07 #Python
Python实现基于C/S架构的聊天室功能详解
Jul 07 #Python
Python实现的txt文件去重功能示例
Jul 07 #Python
Django 多语言教程的实现(i18n)
Jul 07 #Python
python利用requests库进行接口测试的方法详解
Jul 06 #Python
python生成密码字典的方法
Jul 06 #Python
You might like
PHP输出两个数字中间有多少个回文数的方法
2015/03/23 PHP
PHP编程之设置apache虚拟目录
2016/07/08 PHP
一个简单的javascript类定义例子
2009/09/12 Javascript
如何设置iframe高度自适应在跨域情况下的可用方法
2013/09/06 Javascript
jQuery不兼容input的change事件问题解决过程
2014/12/05 Javascript
实例讲解js验证表单项是否为空的方法
2016/01/09 Javascript
利用JS实现数字增长
2016/07/28 Javascript
AngularJS之依赖注入模拟实现
2016/08/19 Javascript
关于js二维数组和多维数组的定义声明(详解)
2016/10/02 Javascript
jQuery dateRangePicker插件使用方法详解
2017/07/28 jQuery
vue scroller返回页面记住滚动位置的实例代码
2018/01/29 Javascript
基于axios 解决跨域cookie丢失的问题
2018/09/26 Javascript
npm 常用命令详解(小结)
2019/01/17 Javascript
js实现简单放大镜效果
2020/03/07 Javascript
如何实现小程序与小程序之间的跳转
2020/11/04 Javascript
Python模块学习 re 正则表达式
2011/05/19 Python
python函数参数*args**kwargs用法实例
2013/12/04 Python
Python中获取网页状态码的两个方法
2014/11/03 Python
python保存字符串到文件的方法
2015/07/01 Python
Python设计模式编程中Adapter适配器模式的使用实例
2016/03/02 Python
Python虚拟环境项目实例
2017/11/20 Python
Python中的默认参数实例分析
2018/01/29 Python
python实现m3u8格式转换为mp4视频格式
2018/02/28 Python
浅谈tensorflow中几个随机函数的用法
2018/07/27 Python
SpringBoot实现登录注册常见问题解决方案
2020/03/04 Python
python 中的命名空间,你真的了解吗?
2020/08/19 Python
Python实现快速大文件比较代码解析
2020/09/04 Python
Python读写锁实现实现代码解析
2020/11/28 Python
基于Python的接口自动化读写excel文件的方法
2021/01/15 Python
python爬虫scrapy框架之增量式爬虫的示例代码
2021/02/26 Python
实例教程 一款纯css3实现的数字统计游戏
2014/11/10 HTML / CSS
印度手工编织服装和家居用品商店:Fabindi
2019/10/07 全球购物
报关专员求职信范文
2014/02/22 职场文书
普通大学毕业生自荐信范文
2014/02/23 职场文书
公司开业致辞
2015/07/29 职场文书
公司出差管理制度范本
2015/08/05 职场文书