# -*- coding: utf-8 -*-
from enum import Enum #参考http://blog.csdn.net/niteip/article/details/11840691/
#参考https://www.cnblogs.com/suimeng/p/4560056.html
#todo 还没有考虑高度的增减,只考虑了平衡因子
#todo 加上非递归遍历二叉树 class BFStatus(Enum):
# 左子树的高度减去右子树的高度 RH,EH,LH分别表示右子树较高,左右子树等高,左子树较高
LH = 1
EH = 0
RH = -1 class TreeNode(object):
def __init__(self):
self.lson = None
self.rson = None
self.pnode = None
self.data = None
self.freq = 0
self.hgt = -1
self.bfstatus = BFStatus().EH class AVLTree(object):
def __init__(self,root_node):
self.root = TreeNode def height(self,node):
if node is not None:
return node.hgt
return -1 def max(self,campa,campb):
if campa > campb:
return campa
else:
return campb def single_rotate_right(self, node): # 右单旋转 RR
parent_node = node.pnode
node1 = node.lson
node.lson = node1.rson
node1.rson = node
if parent_node.lson == node:
parent_node.lson = node1
else:
parent_node.rson = node1
node1.pnode = parent_node
node.pnode = node1 def single_rotate_left(self, node): # 左单旋转 LL
parent_node = node.pnode
node1 = node.rson
node.rson = node1.lson
node1.lson = node
if parent_node.lson == node:
parent_node.lson = node1
else:
parent_node.rson = node1
node1.pnode = parent_node
node.pnode = node1 def LeftBalance(self,node):
lchild = node.lson
BFStatus_code = BFStatus()
if lchild.bfstatus == BFStatus_code.EH:
node.bfstatus = lchild.bfstatus = BFStatus_code.LH
lchild.bfstatus = BFStatus.RH
self.single_rotate_right(node)
elif lchild.bfstatus == BFStatus_code.LH:#LL型
node.bfstatus = lchild.bfstatus = BFStatus.EH
self.single_rotate_right(node)
elif lchild.bfstatus == BFStatus.RH:#LR型
rchild = lchild.rson
if rchild.bfstatus == BFStatus.EH:
node.bfstatus = BFStatus.RH
lchild.bfstatus = BFStatus.EH
elif rchild.bfstatus == BFStatus.LH:
node.bfstatus = BFStatus.EH
lchild.bfstatus = BFStatus.LH
elif rchild.bfstatus == BFStatus.RH:
node.bfstatus = BFStatus.EH
lchild.bfstatus = BFStatus.EH
rchild.bfstatus = BFStatus.EH
self.single_rotate_left(lchild)
self.single_rotate_right(node) def RightBalance(self,node):
rchild = node.rson
BFStatus_code = BFStatus()
if rchild.bfstatus == BFStatus_code.RH:
node.bfstatus = node.bfstatus = BFStatus_code.EH
self.single_rotate_left(node)
elif rchild.bfstatus == BFStatus_code.EH:#LL型
node.bfstatus = rchild.bfstatus = BFStatus.RH
rchild.bfstatus = BFStatus.LH
self.single_rotate_left(node)
elif rchild.bfstatus == BFStatus.LH:#LR型
lchild = rchild.lson
if lchild.bfstatus == BFStatus.LH:
node.bfstatus = BFStatus.EH
rchild.bfstatus = BFStatus.RH
elif lchild.bfstatus == BFStatus.RH:
node.bfstatus = BFStatus.LH
rchild.bfstatus = BFStatus.EH
elif lchild.bfstatus == BFStatus.EH:
node.bfstatus = BFStatus.EH
rchild.bfstatus = BFStatus.EH
lchild.bfstatus = BFStatus.EH
self.single_rotate_right(rchild)
self.single_rotate_left(node) def insertpri(self,node,data,stack_list,taller_param=True):
if node == None:
node = TreeNode()
node.data = data
node.pnode = stack_list[-1]
else:
stack_list.append(node)
if node.data < data:
(sign,taller) = self.insertpri(node.lson,data,stack_list)
if sign == False:
return (False,taller_param) if taller == True: if node.bfstatus == BFStatus().LH:
self.LeftBalance(node)
taller_param = False
elif node.bfstatus == BFStatus().EH:
node.bfstatus = BFStatus().LH
taller_param = True
elif node.bfstatus == BFStatus().RH:
node.bfstatus = BFStatus().EH
taller_param = False elif node.data > data:
stack_list.append(node)
if node.data < data:
(sign, taller) = self.insertpri(node.rson, data, stack_list)
if sign == False:
return (False, taller_param) if taller == True:
if node.bfstatus == BFStatus().LH:
node.bfstatus = BFStatus().EH
taller_param = False
elif node.bfstatus == BFStatus().EH:
node.bfstatus = BFStatus().RH
taller_param = True
elif node.bfstatus == BFStatus().RH:
self.RightBalance(node)
taller_param = False
else:
node.freq += 1 return (True,taller_param) def insert(self,data):
stack_list = []
self.insertpri(self.root,data,stack_list) def searchpri(self,node,data):
if node is None:
return None elif node.data > data:
self.searchpri(node.lson,data) elif node.data < data:
self.searchpri(node.rson,data) else:
return node def search(self,data):
self.searchpri(self.root,data) def go_far_left(self,node):
if node.lson is None:
return node
else:
self.go_far_left(node.lson) def go_far_right(self,node):
if node.rson is None:
return node
else:
self.go_far_right(node.rson) def delete_left(self,node,bfchild):
#当bf为-1或1变为0,或者孩子为空时说明子树高降低
if node.lson is None or (bfchild != BFStatus().EH and node.lson.bfstatus == BFStatus().EH):
#左子树树高降低
if node.bfstatus == BFStatus().EH:
node.bfstatus = BFStatus().RH
elif node.bfstatus == BFStatus().LH:
node.bfstatus = BFStatus().EH
elif node.bfstatus == BFStatus().RH:#原本右子树比较高
self.RightBalance(node) def delete_right(self,node,bfchild):
#当bf为LH或RH变为EH,或者孩子为空时说明子树高降低
if node.rson is None or (bfchild != BFStatus().EH and node.rson.bfstatus == BFStatus().EH):
#左子树树高降低
if node.bfstatus == BFStatus().EH:
node.bfstatus = BFStatus().LH
elif node.bfstatus == BFStatus().RH:
node.bfstatus = BFStatus().EH
elif node.bfstatus == BFStatus().LH:#原本左子树比较高
self.LeftBalance(node) def deletepri(self,node,data):
bfchild = BFStatus().EH
if node == None:
return None
if node.data > data:
bfchild = node.lson.bfstatus
node.lson = self.deletepri(node.lson,data)
self.delete_left(node,bfchild) elif node.data < data:
bfchild = node.rson.bfstatus
node.rson = self.deletepri(node.rson, data)
self.delete_left(node, bfchild) else:
if node.lson is not None: #不是叶子结点并且具有直接前驱
far_right_node = self.go_far_right(node.lson)#直接前驱
node.data = far_right_node.data
node.lson = self.deletepri(node.lson,far_right_node.data)#可以确定,删除的节点为当前节点的左子树的某一个节点
self.delete_left(node,bfchild)
elif node.rson is not None:
far_left_node = self.go_far_left(node.rson)
node.data = far_left_node.data
node.rson = self.deletepri(node.rson,far_left_node.data)
self.delete_right(node,bfchild)
else:#叶子结点
node = None return node def delete(self,data):
self.deletepri(self.root,data) def insubtree(self,node):
if node is None:
return
self.insubtree(node.lson)
print(node.data)
self.insubtree(node.rson) def traversal(self):
self.insubtree(self.root) if __name__ == '__main__':
root_node = TreeNode()
tree_obj = AVLTree(root_node)

  

Python实现自平衡二叉树AVL的更多相关文章

  1. 详细理解平衡二叉树AVL与Python实现

    前言 上一篇文章讨论的二叉搜索树,其时间复杂度最好的情况下是O(log(n)),但是最坏的情况是O(n),什么时候是O(n)呢? 像这样: 如果先插入10,再插入20,再插入30,再插入40就会成上边 ...

  2. 数据结构与算法--从平衡二叉树(AVL)到红黑树

    数据结构与算法--从平衡二叉树(AVL)到红黑树 上节学习了二叉查找树.算法的性能取决于树的形状,而树的形状取决于插入键的顺序.在最好的情况下,n个结点的树是完全平衡的,如下图"最好情况&q ...

  3. 二叉查找树(BST)、平衡二叉树(AVL树)(只有插入说明)

    二叉查找树(BST).平衡二叉树(AVL树)(只有插入说明) 二叉查找树(BST) 特殊的二叉树,又称为排序二叉树.二叉搜索树.二叉排序树. 二叉查找树实际上是数据域有序的二叉树,即对树上的每个结点, ...

  4. 平衡二叉树AVL - 插入节点后旋转方法分析

    平衡二叉树 AVL( 发明者为Adel'son-Vel'skii 和 Landis)是一种二叉排序树,其中每一个节点的左子树和右子树的高度差至多等于1. 首先我们知道,当插入一个节点,从此插入点到树根 ...

  5. 二叉查找树、平衡二叉树(AVL)、B+树、联合索引

    1. [定义] 二叉排序树(二拆查找树)中,左子树都比节点小,右子树都比节点大,递归定义. [性能] 二叉排序树的性能取决于二叉树的层数 最好的情况是 O(logn),存在于完全二叉排序树情况下,其访 ...

  6. Java 树结构实际应用 四(平衡二叉树/AVL树)

    平衡二叉树(AVL 树) 1 看一个案例(说明二叉排序树可能的问题) 给你一个数列{1,2,3,4,5,6},要求创建一颗二叉排序树(BST), 并分析问题所在.  左边 BST 存在的问题分析: ...

  7. 【数据结构】平衡二叉树—AVL树

    (百度百科)在计算机科学中,AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下都是O(log n).增 ...

  8. 平衡二叉树AVL删除

    平衡二叉树的插入过程:http://www.cnblogs.com/hujunzheng/p/4665451.html 对于二叉平衡树的删除采用的是二叉排序树删除的思路: 假设被删结点是*p,其双亲是 ...

  9. 平衡二叉树AVL插入

    平衡二叉树(Balancedbinary tree)是由阿德尔森-维尔斯和兰迪斯(Adelson-Velskiiand Landis)于1962年首先提出的,所以又称为AVL树. 定义:平衡二叉树或为 ...

随机推荐

  1. HDU1712:ACboy needs your help(分组背包模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=1712 Problem Description ACboy has N courses this term, an ...

  2. 计算auc-python/awk

    1.自己写的计算auc的代码,用scikit-learn的auc计算函数sklearn.metrics.auc(x, y, reorder=False)做了一些测试,结果是一样的,如有错误,欢迎指正. ...

  3. 用python写http接口自动化测试框架

    本文是转载张元礼的博客 http://blog.csdn.Net/vincetest 一.测试需求描述 对服务后台一系列的http接口功能测试. 输入:根据接口描述构造不同的参数输入值 输出:XML文 ...

  4. qt用mingw编译时报错 multiple definition of

    网上相关回答不少,但过于简单,这里做一下记录. qt用mingw编译程序时报“multiple definition of …”这个错误,错误信息大概是如下图所示: 1 2 3 首先,检查自己的程序是 ...

  5. Vim/Vi的使用

     Vim 是vi的加强 Gvim图形化的vim Vim/Vi简介 Vim/Vi是一个功能强大的全屏幕文本编辑器,是Linux/Unix上最常用的文本编辑器,他们 的作用是建立,编辑,显示文本文件 Vi ...

  6. JS的增删改查

    1.查 <script type="text/javascript"> /** * 查找 已经在html代码中存在的元素 */ /** * document.getEl ...

  7. Redis 十分钟快速入门

    本教程是一个快速入门教程,所以Redis的命令只是简单介绍了几个常用的,如果有其他需求请求官网查看API 使用. 1. Redis简介 Redis 是完全开源免费的,遵守BSD协议,是一个高性能的ke ...

  8. Firefox及我使用的firefox扩展

    什么数字安全浏览器,什么极速浏览器,现在都取代不了Firefox在我心中的位置.你想想,一款浏览器老是弹呀弹的,时不时问我换不换桌面,问我请不清理垃圾,真是的,这些关它浏览器鸟事. 喜欢Firefox ...

  9. STA分析(二) multi_cycle and false

    multicycle path:当FF之间的组合逻辑path propagate delay大于一个时钟cycle时,这条combinational path能被称为multicycle path. ...

  10. VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)

    上一节讲了标签控件Tab Control以后,常用控件的内容就全部讲完了,当然并没有包括所有控件,主要是一些很常用很重要的控件.本节开始鸡啄米将为大家讲解菜单的概念及使用. 菜单简介 菜单在界面设计中 ...