[从头学数学] 第243节 关于平衡二叉树的Python实现

来源:互联网 发布:php continue 编辑:程序博客网 时间:2024/05/16 14:49
剧情提要:
阿伟看到了一本比较有趣的书,是关于《计算几何》的,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
原创粉丝点击