[工程师阿伟]正在和[机器小伟]一起研究[计算几何]]。
关于平衡二叉树ALV,一直没有找到Python版本,当然C++和Java版本有很多。
于是想自己实现一个。
首先研究了下二叉查找树:
#用列表模拟平衡二叉树
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];
结论就是这种树是没用的,也没有研究下去的价值了。
接着看ALV树。
###
# @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;
然后到插入就卡壳了,怎么都调不出结果来。
下面这是废码,留着看看吧:
#插入
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);
阿伟最后终于发现了问题所在,在C++中可以用*号给每个节点作为存储地址,
在Java里面也可以用&,虽然效果差了点,但在Python里面,啥都没有。
插入函数中需要不断地new出新地址来存储节点,但这确实是做不到的。
当然,只要解决了每个节点的存储空间问题,用Python也是可以实现这个ALV树的。
用链表来存也不是不可以,但那样效率肯定会非常差。
那是不是可以这么说: Python可以和数据结构说拜拜了呢。
本节到此结束,欲知后事如何,请看下回分解。