AVL树是带有平衡条件的二叉查找树,一般要求每个节点的左子树和右子树的高度最多差1(空树的高度定义为-1)。

在高度为h的AVL树中,最少的节点数S(h)由S(h)=S(h-1)+S(h-2)+1得出,其中S(0)=1,S(1)=2。

如上图,分别为高度为0,1,2,3的AVL树所需要的最少节点数。

1.AVL树的实现,遍历与查找操作与二叉查找树相同。

class Node(object):
def __init__(self,key):
self.key=key
self.left=None
self.right=None
self.height=0
class AVLTree(object):
def __init__(self):
self.root=None
def find(self,key):
if self.root is None:
return None
else:
return self._find(key,self.root)
def _find(self,key,node):
if node is None:
return None
elif key<node.key:
return self._find(key,self.left)
elif key>node.key:
return self._find(key,self.right)
else:
return node
def findMin(self):
if self.root is None:
return None
else:
return self._findMin(self.root)
def _findMin(self,node):
if node.left:
return self._findMin(node.left)
else:
return node
def findMax(self):
if self.root is None:
return None
else:
return self._findMax(self.root)
def _findMax(self,node):
if node.right:
return self._findMax(node.right)
else:
return node
def height(self,node):
if node is None:
return -1
else:
return node.height

2.AVL树的插入操作

插入一个节点可能会破坏AVL树的平衡,可以通过旋转操作来进行修正。

插入一个节点后,只有从插入节点到根节点的路径上的节点的平衡可能被改变。我们需要找出第一个破坏了平衡条件的节点,称之为K。K的两颗子树的高度差2。

不平衡有四种情况:

1.对K的左儿子的左子树进行一次插入

2.对K的左儿子的右子树进行一次插入

3.对K的右儿子的左子树进行一次插入

4.对K的右儿子的右子树进行一次插入

情况1与4是对称的,需要进行一次单旋转操作,清况2与3需要一次双旋转操作。

情况1:

    def singleLeftRotate(self,node):
k1=node.left
node.left=k1.right
k1.right=node
node.height=max(self.height(node.right),self.height(node.left))+1
k1.height=max(self.height(k1.left),node.height)+1
return k1

  

情况4:

def singleRightRotate(self,node):
k1=node.right
node.right=k1.left
k1.left=node
node.height=max(self.height(node.right),self.height(node.left))+1
k1.height=max(self.height(k1.right),node.height)+1
return k1

情况3:

相当于进行了两次单旋转。

def doubleRightRotate(self,node):
node.right=self.singleLeftRotate(node.right)
return self.singleRightRotate(node)

情况2:

与情况3类似,都是进行了2次单旋转。

def doubleLeftRotate(self,node):
node.left=self.singleRightRotate(node.left)
return self.singleLeftRotate(node)

一系列插入操作:

插入代码如下:

    def put(self,key):
if not self.root:
self.root=Node(key)
else:
self.root=self._put(key,self.root)
def _put(self,key,node):
if node is None:
node=Node(key)
elif key<node.key:
node.left=self._put(key,node.left)
if (self.height(node.left)-self.height(node.right))==2:
if key<node.left.key:
node=self.singleLeftRotate(node)
else:
node=self.doubleLeftRotate(node) elif key>node.key:
node.right=self._put(key,node.right)
if (self.height(node.right)-self.height(node.left))==2:
if key<node.right.key:
node=self.doubleRightRotate(node)
else:
node=self.singleRightRotate(node) node.height=max(self.height(node.right),self.height(node.left))+1
return node

3.AVL树的删除操作:

删除操作比较复杂,如有错误,请指正。

1.当前节点为要删除的节点且是树叶(无子树),直接删除,当前节点(为None)的平衡不受影响。

2.当前节点为要删除的节点且只有一个左儿子或右儿子,用左儿子或右儿子代替当前节点,当前节点的平衡不受影响。

3.当前节点为要删除的节点且有左子树右子树:如果右子树高度较高,则从右子树选取最小节点,将其值赋予当前节点,然后删除右子树的最小节点。如果左子树高度较高,则从左子树选取最大节点,将其值赋予当前节点,然后删除左子树的最大节点。这样操作当前节点的平衡不会被破坏。

4.当前节点不是要删除的节点,则对其左子树或者右子树进行递归操作。当前节点的平衡条件可能会被破坏,需要进行平衡操作。

如上图,25为当前节点,左子树删除17后平衡条件被破坏,需要根据当前节点(25)的右子树(30)的左子树(28)高度是否高于右子树(35)的高度进行判断,若高于,进行双旋转,否则进行单旋转

    def delete(self,key):
self.root=self.remove(key,self.root)
def remove(self,key,node):
if node is None:
raise KeyError,'Error,key not in tree'
elif key<node.key:
node.left=self.remove(key,node.left)
if (self.height(node.right)-self.height(node.left))==2:
if self.height(node.right.right)>=self.height(node.right.left):
node=self.singleRightRotate(node)
else:
node=self.doubleRightRotate(node)
node.height=max(self.height(node.left),self.height(node.right))+1 elif key>node.key:
node.right=self.remove(key,node.right)
if (self.height(node.left)-self.height(node.right))==2:
if self.height(node.left.left)>=self.height(node.left.right):
node=self.singleLeftRotate(node)
else:
node=self.doubleLeftRotate(node)
node.height=max(self.height(node.left),self.height(node.right))+1 elif node.left and node.right:
if node.left.height<=node.right.height:
minNode=self._findMin(node.right)
node.key=minNode.key
node.right=self.remove(node.key,node.right)
else:
maxNode=self._findMax(node.left)
node.key=maxNode.key
node.left=self.remove(node.key,node.left)
node.height=max(self.height(node.left),self.height(node.right))+1
else:
if node.right:
node=node.right
else:
node=node.left return node

  

全部代码:

class Node(object):
def __init__(self,key):
self.key=key
self.left=None
self.right=None
self.height=0
class AVLTree(object):
def __init__(self):
self.root=None
def find(self,key):
if self.root is None:
return None
else:
return self._find(key,self.root)
def _find(self,key,node):
if node is None:
return None
elif key<node.key:
return self._find(key,self.left)
elif key>node.key:
return self._find(key,self.right)
else:
return node
def findMin(self):
if self.root is None:
return None
else:
return self._findMin(self.root)
def _findMin(self,node):
if node.left:
return self._findMin(node.left)
else:
return node
def findMax(self):
if self.root is None:
return None
else:
return self._findMax(self.root)
def _findMax(self,node):
if node.right:
return self._findMax(node.right)
else:
return node
def height(self,node):
if node is None:
return -1
else:
return node.height def singleLeftRotate(self,node):
k1=node.left
node.left=k1.right
k1.right=node
node.height=max(self.height(node.right),self.height(node.left))+1
k1.height=max(self.height(k1.left),node.height)+1
return k1
def singleRightRotate(self,node):
k1=node.right
node.right=k1.left
k1.left=node
node.height=max(self.height(node.right),self.height(node.left))+1
k1.height=max(self.height(k1.right),node.height)+1
return k1
def doubleLeftRotate(self,node):
node.left=self.singleRightRotate(node.left)
return self.singleLeftRotate(node)
def doubleRightRotate(self,node):
node.right=self.singleLeftRotate(node.right)
return self.singleRightRotate(node)
def put(self,key):
if not self.root:
self.root=Node(key)
else:
self.root=self._put(key,self.root)
def _put(self,key,node):
if node is None:
node=Node(key)
elif key<node.key:
node.left=self._put(key,node.left)
if (self.height(node.left)-self.height(node.right))==2:
if key<node.left.key:
node=self.singleLeftRotate(node)
else:
node=self.doubleLeftRotate(node) elif key>node.key:
node.right=self._put(key,node.right)
if (self.height(node.right)-self.height(node.left))==2:
if key<node.right.key:
node=self.doubleRightRotate(node)
else:
node=self.singleRightRotate(node) node.height=max(self.height(node.right),self.height(node.left))+1
return node def delete(self,key):
self.root=self.remove(key,self.root)
def remove(self,key,node):
if node is None:
raise KeyError,'Error,key not in tree'
elif key<node.key:
node.left=self.remove(key,node.left)
if (self.height(node.right)-self.height(node.left))==2:
if self.height(node.right.right)>=self.height(node.right.left):
node=self.singleRightRotate(node)
else:
node=self.doubleRightRotate(node)
node.height=max(self.height(node.left),self.height(node.right))+1 elif key>node.key:
node.right=self.remove(key,node.right)
if (self.height(node.left)-self.height(node.right))==2:
if self.height(node.left.left)>=self.height(node.left.right):
node=self.singleLeftRotate(node)
else:
node=self.doubleLeftRotate(node)
node.height=max(self.height(node.left),self.height(node.right))+1 elif node.left and node.right:
if node.left.height<=node.right.height:
minNode=self._findMin(node.right)
node.key=minNode.key
node.right=self.remove(node.key,node.right)
else:
maxNode=self._findMax(node.left)
node.key=maxNode.key
node.left=self.remove(node.key,node.left)
node.height=max(self.height(node.left),self.height(node.right))+1
else:
if node.right:
node=node.right
else:
node=node.left return node

  

  

AVL树的python实现的更多相关文章

  1. AVL树插入(Python实现)

    建立AVL树 class AVLNode(object): def __init__(self,data): self.data = data self.lchild = None self.rchi ...

  2. AVL树Python实现(使用递推实现添加与删除)

    # coding=utf-8 # AVL树的Python实现(树的节点中包含了指向父节点的指针) def get_height(node): return node.height if node el ...

  3. AVL树Python实现

    # coding=utf-8 # AVL树Python实现 def get_height(node): return node.height if node else -1 def tree_mini ...

  4. python常用算法(5)——树,二叉树与AVL树

    1,树 树是一种非常重要的非线性数据结构,直观的看,它是数据元素(在树中称为节点)按分支关系组织起来的结构,很像自然界中树那样.树结构在客观世界中广泛存在,如人类社会的族谱和各种社会组织机构都可用树形 ...

  5. 【数据结构与算法Python版学习笔记】树——平衡二叉搜索树(AVL树)

    定义 能够在key插入时一直保持平衡的二叉查找树: AVL树 利用AVL树实现ADT Map, 基本上与BST的实现相同,不同之处仅在于二叉树的生成与维护过程 平衡因子 AVL树的实现中, 需要对每个 ...

  6. AVL树探秘

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev) ,专注于干货分享,号内有 10T 书籍和视频资源,后台回复 「1024」 即可领取,欢迎大家关注,二维码文末可以扫. 一.AV ...

  7. 数据结构中的树(二叉树、二叉搜索树、AVL树)

    数据结构动图展示网站 树的概念 树(英语:tree)是一种抽象数据类型(ADT)或是实作这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合.它是由n(n>=1)个有限节点组成一个具有 ...

  8. 算法与数据结构(十一) 平衡二叉树(AVL树)

    今天的博客是在上一篇博客的基础上进行的延伸.上一篇博客我们主要聊了二叉排序树,详情请戳<二叉排序树的查找.插入与删除>.本篇博客我们就在二叉排序树的基础上来聊聊平衡二叉树,也叫AVL树,A ...

  9. AVL树原理及实现(C语言实现以及Java语言实现)

    欢迎探讨,如有错误敬请指正 如需转载,请注明出处http://www.cnblogs.com/nullzx/ 1. AVL定义 AVL树是一种改进版的搜索二叉树.对于一般的搜索二叉树而言,如果数据恰好 ...

随机推荐

  1. ASP.NET MVC 4 批量上传文件

    上传文件的经典写法: <form id="uploadform" action="/Home/UploadFile" method="post& ...

  2. POWER DESIGN

    一.概念数据模型概述数据模型是现实世界中数据特征的抽象.数据模型应该满足三个方面的要求:1)能够比较真实地模拟现实世界2)容易为人所理解3)便于计算机实现 概念数据模型也称信息模型,它以实体-联系(E ...

  3. Selector中的各种状态详解

    今天弄这个selector把脑壳弄得清痛,最终我的理解如下: 官方关于这个的介绍在:http://developer.android.com/guide/topics/resources/drawab ...

  4. ios二维码扫描插件,适配当前主流扫描软件,自定义扫描界面。

            二维码介绍: 二维码(QR(Quick Response)code),又称二维条码,最早起源于日本. 它是用特定的几何图形按一定规律在平面(二维方向)上分布的黑白相间的图形,是所有信息 ...

  5. Tire树

    Trie树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种. 典型应用是用于统计和排序大量的字符串(但不仅限于字符串), 所以经常被搜索引擎系统用于文本词频统计. 字典树(Trie)可以保存 ...

  6. hishop网站迁移后出现DataProtectionConfigurationProvider错误(转)

    配置错误说明: 在处理向该请求提供服务所需的配置文件时出错.请检查下面的特定错误详细信息并适当地修改配置文件.分析器错误信息: 未能使用提供程序“DataProtectionConfiguration ...

  7. asp.net上传大文件

    Asp.net默认允许上传文件的最大值为4M. 如果想要上传更大的文件,需要修改web.config文件,方法是: 在<system.web>节点中添加代码 <httpRuntime ...

  8. Jackson - Quickstart

    JSON Three Ways Jackson offers three alternative methods (one with two variants) for processing JSON ...

  9. TSQL基础(二)

    over() 开窗函数 排名函数必须和over()一起使用,所以先了解over(). OVER 子句定义查询结果集内的窗口或用户指定的行集. 然后,开窗函数将计算窗口中每一行的值. 您可以将 OVER ...

  10. OpenMP多线程linux下的使用,简单化

    http://hi.baidu.com/diwulechao/item/bc6d865c411b813c32e0a932 http://www.cnblogs.com/yangyangcv/archi ...