[从头学数学] 第243节 关于平衡二叉树的Python实现
2016-07-23 16:41
681 查看
剧情提要:
阿伟看到了一本比较有趣的书,是关于《计算几何》的,2008年由北清派出版。很好奇
它里面讲了些什么,就来看看啦。
正剧开始:
星历2016年07月23日 16:30:59, 银河系厄尔斯星球中华帝国江南行省。
[工程师阿伟]正在和[机器小伟]一起研究[计算几何]]。
关于平衡二叉树ALV,一直没有找到Python版本,当然C++和Java版本有很多。
于是想自己实现一个。
首先研究了下二叉查找树:
据说这种树有退化的问题,只写了这一个函数,这个问题就暴露了。
结论就是这种树是没用的,也没有研究下去的价值了。
接着看ALV树。
左旋,右旋,左平衡,右平衡都没有问题。
然后到插入就卡壳了,怎么都调不出结果来。
下面这是废码,留着看看吧:
阿伟最后终于发现了问题所在,在C++中可以用*号给每个节点作为存储地址,
在Java里面也可以用&,虽然效果差了点,但在Python里面,啥都没有。
插入函数中需要不断地new出新地址来存储节点,但这确实是做不到的。
当然,只要解决了每个节点的存储空间问题,用Python也是可以实现这个ALV树的。
用链表来存也不是不可以,但那样效率肯定会非常差。
那是不是可以这么说: Python可以和数据结构说拜拜了呢。
本节到此结束,欲知后事如何,请看下回分解。
阿伟看到了一本比较有趣的书,是关于《计算几何》的,2008年由北清派出版。很好奇
它里面讲了些什么,就来看看啦。
正剧开始:
星历2016年07月23日 16:30:59, 银河系厄尔斯星球中华帝国江南行省。
[工程师阿伟]正在和[机器小伟]一起研究[计算几何]]。
关于平衡二叉树ALV,一直没有找到Python版本,当然C++和Java版本有很多。
于是想自己实现一个。
首先研究了下二叉查找树:
<span style="font-size:18px;">#用列表模拟平衡二叉树 class BBT(): #对于按<法则排序好的列表,查看其中任意元素的左右叶子,返回序号 #二叉查找树,会有退化现象 def childindex(self, total, cur, mode = 'L'): #total: 列表总元素数,位序取值范围 0 ~ total-1 #cur: 当前元素在列表中的位序 start = 0; end = total-1; if (cur == start or cur == end): return [cur, -1, -1, math.ceil(math.log(total)/math.log(2))-1]; midArray = []; mid = (start + end+1)//2; left = (start + mid+1)//2; right = (mid + end+1)//2; level = 0; midArray.append(mid); while (mid != cur and level < 10): if (mid < cur): start = mid; mid_ = (end + mid+1)//2; right = (end + mid_+1)//2; left = (mid + mid_+1)//2; mid = mid_; elif (mid > cur): end = mid; mid_ = (start + mid+1)//2; right = (mid+mid_+1)//2; left = (start+mid_+1)//2; mid = mid_; midArray.append(mid); level+=1; if (left in midArray): left = -1; if (right in midArray): right = -1; return [cur, left, right, level]; </span>
据说这种树有退化的问题,只写了这一个函数,这个问题就暴露了。
结论就是这种树是没用的,也没有研究下去的价值了。
接着看ALV树。
<span style="font-size:18px;">### # @usage 平衡二叉树的Python实现,C++/Java实现到处都有 # @author mw # @date 2016年07月23日 星期六 10:09:31 # @param # @return # ### #AVL树 class ALVTreeNode(): def __init__(self, data, height, freq, left, right): self.data = data; self.height = height; self.freq = freq; self.left = left; self.right = right; #小于<法则 def less(x1, x2): return x1 < x2; class ALVTree(): def __init__(self): self.root = None; self.left = None; self.right = None; def setValue(self, root, left, right): self.root = root; self.left = left; self.right = right; def getValue(self): return [self.root, self.left, self.right]; def info(self, node): if (node == None): info = 'None'; else: if (node.left == None): sL = 'None'; else: sL = node.left.data; if (node.right == None): sR = 'None'; else: sR = node.right.data; info = [node.data, node.height, node.freq, sL, sR]; print(info); def genNode(self, data, height, freq, left, right): return ALVTreeNode(data, height, freq, left, right); def height(self, node): if (node == None): return 0; else: lh = self.height(node.left); rh = self.height(node.right); node.height = max(lh, rh)+1; return node.height; #左左情况下的旋转 #输入的是高度最高的节点,也就是待处理的root def rotateLL(self, k2): k1 = k2.left; k2.left = k1.right; k1.right = k2; k2.height = max(self.height(k2.left), self.height(k2.right))+1; k1.height = max(self.height(k1.left), k2.height)+1; return k1; #右右情况下的旋转 #输入的是高度最高的节点,也就是待处理的root def rotateRR(self, k2): k1 = k2.right; k2.right = k1.left; k1.left = k2; k2.height = max(self.height(k2.left), self.height(k2.right))+1; k1.height = max(self.height(k1.right), k2.height)+1; return k1; #左右情况的旋转 #输入的是高度最高的节点,也就是待处理的root def rotateLR(self, k3): k1 = self.rotateRR(k3.left); k3.left = k1; k2 = self.rotateLL(k3); return k2; #右左情况的旋转 #输入的是高度最高的节点,也就是待处理的root def rotateRL(self, k3): k1 = self.rotateLL(k3.right); k3.right = k1; k2 = self.rotateRR(k3); return k2; #平衡值 def balanceFlag(self, node): return self.height(node.left)-self.height(node.right); #左平衡 def LBalance(self, root): p = root; c = p.left; rc = c.right; cbf = self.balanceFlag(c); if (cbf == 1): root = self.rotateLL(root); elif (cbf == -1): root = self.rotateLR(root); return root; #右平衡 def RBalance(self, root): p = root; c = p.right; lc = c.left; cbf = self.balanceFlag(c); if (cbf == -1): root = self.rotateRR(root); elif (cbf == 1): root = self.rotateRL(root); return root; </span>
左旋,右旋,左平衡,右平衡都没有问题。
然后到插入就卡壳了,怎么都调不出结果来。
下面这是废码,留着看看吧:
<span style="font-size:18px;"> #插入 def insert_x(self, node, data): if (node == None): node = self.genNode(data, 1, 0, None, None); return node; else: if (less(data, node.data)): if (node.left == None): node.left = self.genNode(data, 1, 0, None, None); self.height(node); if (2 == self.height(node.left) - self.height(node.right)): if less(data, node.left.data): self.rotateLL(node); else: self.rotateLR(node); return node; else: return self.insert(node.left, data); elif (less(node.data, data)): if (node.right == None): node.right = self.genNode(data, 1, 0, None, None); self.height(node); if (2 == self.height(node.right) - self.height(node.left)): if less(node.right.data, data): self.rotateRR(node); else: self.rotateRL(node); return node; else: return self.insert(node.right, data); else: #如果相等,就把频率加1 node.freq+=1; #插入 def insert(self, root, data, tall = 1): if (root == None): tall = 1; root = self.genNode(data, 1, 0, None, None); self.setValue(root, root.left, root.right); return 1; elif (root.data == data): #如果相等,就把频率加1 root.freq+=1; self.setValue(root, root.left, root.right); return 0; elif (less(data, root.data)): if (root.left == None): self.setValue(root, self.genNode(data, 1, 0, None, None), root.right); return 1; else: self.insert(root.left, data, tall): if (tall): root = self.root; rbf = self.balanceFlag(root); if (rbf == 1): root = LBalance(root); tall = 0; elif (rbf == 0): tall = 1; elif (rbf == -1): tall = 0; self.root = root; return 0; elif (less(root.data, data)): if (self.insert(root.right, data, tall)): return 1; if (tall): rbf = self.balanceFlag(root); if (rbf == -1): root = RBalance(root); tall = 0; elif (rbf == 0): tall = 1; elif (rbf == 1): tall = 0; self.root = root; return 0; if __name__ == '__main__': alv = ALVTree(); alv.insert(None, 0); root = alv.root; alv.info(root); for i in range(3): alv.insert(root, i); root = alv.root; alv.info(root);</span>
阿伟最后终于发现了问题所在,在C++中可以用*号给每个节点作为存储地址,
在Java里面也可以用&,虽然效果差了点,但在Python里面,啥都没有。
插入函数中需要不断地new出新地址来存储节点,但这确实是做不到的。
当然,只要解决了每个节点的存储空间问题,用Python也是可以实现这个ALV树的。
用链表来存也不是不可以,但那样效率肯定会非常差。
那是不是可以这么说: Python可以和数据结构说拜拜了呢。
本节到此结束,欲知后事如何,请看下回分解。
相关文章推荐
- Python脚本通过邮件发送zabbix报警图片
- NLP(一)word2Vec实验
- Python——HelloPython
- 习题17 更多文件操作
- python中assertion异常
- python——类
- 初探Python(2)
- Python:时间模块:time和datetime
- 以写代学:python 数据类型之字符串,判断用户输入的id是否符合要求
- Python笔记(5)类__方法与继承
- python set
- Python学习(Leetcode 算法题解【21~40】)
- 习题16 读写文件
- 在python 中is和= = 的区别
- Python定时任务框架APScheduler 3.0.3 Cron示例
- 菜鸟初识python request属性及方法说明
- python的Tidy工具安装
- python的Tidy工具安装
- python的Tidy工具安装
- python的Tidy工具安装