[从头学数学] 第243节 关于平衡二叉树的Python实现
来源:互联网 发布:php continue 编辑:程序博客网 时间:2024/05/16 14:49
剧情提要:
阿伟看到了一本比较有趣的书,是关于《计算几何》的,2008年由北清派出版。很好奇
它里面讲了些什么,就来看看啦。
正剧开始:
星历2016年07月23日 16:30:59, 银河系厄尔斯星球中华帝国江南行省。
据说这种树有退化的问题,只写了这一个函数,这个问题就暴露了。
左旋,右旋,左平衡,右平衡都没有问题。
阿伟看到了一本比较有趣的书,是关于《计算几何》的,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可以和数据结构说拜拜了呢。
本节到此结束,欲知后事如何,请看下回分解。
0 0
- [从头学数学] 第243节 关于平衡二叉树的Python实现
- [从头学数学] 第257节 Python实现数据结构:平衡二叉树(AVL)
- [从头学数学] 第259节 Python实现数据结构:平衡多路搜索树(B-Tree)
- [从头学数学] 第251节 Python实现数据结构:二叉查找树
- [从头学数学] 第244节 Python实现数据结构:列表
- [从头学数学] 第245节 Python实现数据结构:排序
- [从头学数学] 第246节 Python实现数据结构:链表
- [从头学数学] 第247节 Python实现数据结构:栈
- [从头学数学] 第248节 Python实现数据结构:队列
- [从头学数学] 第255节 Python实现数据结构:字典树(Trie)
- [从头学数学] 第258节 Python实现数据结构:伸展树(splay tree)
- [从头学数学] 第260节 Python实现数据结构:B+树
- [从头学数学] 第249节 Python实现数据结构:集合(HashSet)
- [从头学数学] 第250节 Python实现数据结构:映射(HashMap, Dict)
- [从头学数学] 第252节 Python实现数据结构:图(Graph)
- [从头学数学] 第253节 Python实现数据结构:比特集(BitSet)
- [从头学数学] 第254节 Python实现数据结构:bloom Filter
- [从头学数学] 第256节 Python实现数据结构:堆(Heap)
- js常用正则表达式
- Counting Bits
- 二分
- Android初学之Parcel和Parcelable
- OpenCV | Windows 配置 opencv
- [从头学数学] 第243节 关于平衡二叉树的Python实现
- QMenuBar
- ANDROID内存优化(大汇总)
- poj 3641 Pseudoprime numbers
- Android 底部弹出式菜单
- java反射的应用(Hibernate)
- 让dedecms搜索页面支持标签调用及自定义字段调用的方法
- 经典算法面试题目-判断两个字符串是否是变位词(1.4)
- 009-合并表记录