[从头学数学] 第258节 Python实现数据结构:伸展树(splay tree)

剧情提要:
阿伟看到了一本比较有趣的书,是关于《计算几何》的,2008年由北清派出版。很好奇
它里面讲了些什么,就来看看啦。


正剧开始:
星历2016年09月07日 08:41:50, 银河系厄尔斯星球中华帝国江南行省。

[工程师阿伟]正在和[机器小伟]一起研究[计算几何]]。

[从头学数学] 第258节 Python实现数据结构:伸展树(splay tree)_第1张图片


[从头学数学] 第258节 Python实现数据结构:伸展树(splay tree)_第2张图片

#
###
# @usage   splayTree(伸展树),具有根元素记忆及动态调整功能的二叉搜索树
# @author  mw
# @date    2016年09月07日  星期三  08:37:17 
# @param
# @return
#
###
class SplayTree(object):      
    class __SplayNode(object):
        def __init__(self, key, left = None, right = None):
            self.key=key
            self.left=left
            self.right=right

        def __iter__(self):
            if self.left != None:
                for elem in self.left:
                    yield elem

            if (self.key != None):
                yield self.key

            if self.right != None:
                for elem in self.right:
                    yield elem

        #迭代的是Node类型,用于删除结点
        def iternodes(self):
            if self.left != None:
                for elem in self.left.iternodes():
                    yield elem

            if self != None and self.key != None:
                yield self

            if self.right != None:
                for elem in self.right.iternodes():
                    yield elem

        def info(self):
            s = 'Key='+str(self.key)+', '+\
                'LChild='+str(self.left)+', '+\
                'RChild='+str(self.right);
            print(s);
            
        def __str__(self):
            return str(self.key);

        def __repr__(self):
            if self != None:
                s_1 = str(self.key);
            else:
                s_1 = 'None';

            if self.left != None:
                s_2 = str(self.left.key);
            else:
                s_2 = 'None';

            if self.right != None:
                s_3 = str(self.right.key);
            else:
                s_3 = 'None';
                
            return '__SplayNode('+s_1+', ' + s_2 +', ' + s_3 +')';

        
    def __init__(self):
        self.root=None
        self.header = SplayTree.__SplayNode(None) #For splay()

    #LL
    def singleLeftRotate(self,node):
        k1=node.left
        node.left=k1.right
        k1.right=node
        return k1
    
    #RR
    def singleRightRotate(self,node):
        k1=node.right
        node.right=k1.left
        k1.left=node
        return k1
        
    #RL
    def doubleLeftRotate(self,node):
        node.left=self.singleRightRotate(node.left)
        return self.singleLeftRotate(node)
        
    #LR
    def doubleRightRotate(self,node):
        node.right=self.singleLeftRotate(node.right)
        return self.singleRightRotate(node)

    #伸展运动
    def splay(self, key):
        l = r = self.header  
        t = self.root  
        if t is None:  
            return
        
        self.header.left = self.header.right = None
        
        while True:
            if key < t.key:                
                if t.left == None:
                    break;
                if key < t.left.key:
                    t = self.singleLeftRotate(t);
                    if t.left == None:
                        break;
                r.left = t  
                r = t  
                t = t.left 
                
            elif key > t.key:
                if t.right == None:
                    break;
                if key > t.right.key:
                    t = self.singleRightRotate(t);
                    if t.right == None:
                        break;
                l.right = t  
                l = t  
                t = t.right 
            else:
                break;

        l.right = t.left  
        r.left = t.right  
        t.left = self.header.right  
        t.right = self.header.left  
        self.root = t

        
    #
    #和splay操作捆绑的方法
    #
    
    #插入
    def insert(self, key):  
        if (self.root == None):  
            self.root = SplayTree.__SplayNode(key)  
            return  
  
        self.splay(key)  
        if self.root.key == key:  
            # If the key is already there in the tree, don't do anything.  
            return  
  
        n = SplayTree.__SplayNode(key)  
        if key < self.root.key:  
            n.left = self.root.left  
            n.right = self.root  
            self.root.left = None  
        else:  
            n.right = self.root.right  
            n.left = self.root  
            self.root.right = None  
        self.root = n

    def remove(self, key):  
        self.splay(key)  
        if self.root is None or key != self.root.key:  
            return None;
  
        # Now delete the root.  
        if self.root.left== None:  
            self.root = self.root.right  
        else:  
            x = self.root.right  
            self.root = self.root.left  
            self.splay(key)  
            self.root.right = x

        return key;
        
  
    def findMin(self):  
        if self.root == None:  
            return None  
        x = self.root  
        while x.left != None:  
            x = x.left  
        self.splay(x.key)  
        return x.key  
  
    def findMax(self):  
        if self.root == None:  
            return None  
        x = self.root  
        while (x.right != None):  
            x = x.right  
        self.splay(x.key)  
        return x.key  
  
    def find(self, key):  
        if self.root == None:  
            return None  
        self.splay(key)  
        if self.root.key != key:  
            return None  
        return self.root.key  
  
    def isEmpty(self):  
        return self.root == None


    #
    #结构信息查询,不与splay操作捆绑
    #
    
    def getRoot(self):
        return repr(self.root);

    def info(self):
        a = [];
        for x in self:
            a.append(x);

        print(a);

    def __iter__(self):
        if self.root != None:
            return self.root.__iter__()
        else:
            return [].__iter__()

    def __contains__(self, val):
        for x in self:
            if (x == val):
                return True;

        return False;

    def __len__(self):
        a = [];
        for x in self:
            a.append(x);

        return len(a);

    #求结点高度
    def height(self, node):
        if (node == None):
            return 0;
        else:
            m = self.height(node.left);
            n = self.height(node.right);
            return max(m, n)+1;

        #传回结点的原始信息
    def iternodes(self):
        if self.root != None:
            return self.root.iternodes()
        else:
            return [None];

    #寻找节点路径
    def findNodePath(self, root, node):
        path = [];
        if root == None or root.key == None:
            path = [];
            return path
            
        while (root != node):
            if node.key < root.key:
                path.append(root);
                root = root.left;
            elif node.key >= root.key:
                path.append(root);
                root = root.right;
            else:
                break;

        path.append(root);
        return path;

    #寻找父结点
    def parent(self, root, node):
        path = self.findNodePath(root, node);
        if (len(path)>1):
            return path[-2];
        else:
            return None;

    #是否左孩子
    def isLChild(self, parent, lChild):
        if (parent.getLeft() != None and parent.getLeft() == lChild):
            return True;

        return False;

    #是否右孩子
    def isRChild(self, parent, rChild):
        if (parent.getRight() != None and parent.getRight() == rChild):
            return True;

        return False;

    #求某元素是在树的第几层
    #约定根为0层
    #这个计算和求结点的Height是不一样的
    def level(self, elem):
        if self.root != None:
            node = self.root;
            lev = 0;

            while (node != None):
                if elem < node.key:
                    node = node.left;
                    lev+=1;
                elif elem > node.key:
                    node = node.right;
                    lev+=1;
                else:
                    return lev;

            return -1;

        else:
            return -1;

#

用例:

#
if __name__ == '__main__':
    splay = SplayTree();
    
    a = [20, 30, 40, 120, 13, 39, 38, 40, 18, 101];

    for item in a:
        splay.insert(item);
        print(splay.getRoot());
        print(splay.height(splay.root));

    splay.info();
    print(len(splay));

    for node in splay.iternodes():
        print(splay.findNodePath(splay.root, node), '\n');


    '''
    for item in reversed(a):
        print('remove:', splay.remove(item));
        splay.getRoot();
        print(splay.height(splay.root));

    '''

    print(splay.findMax());
    print(splay.getRoot());
	
>>>
__SplayNode(20, None, None)
1
__SplayNode(30, 20, None)
2
__SplayNode(40, 30, None)
3
__SplayNode(120, 40, None)
4
__SplayNode(13, None, 20)
4
__SplayNode(39, 30, 40)
4
__SplayNode(38, 30, 39)
4
__SplayNode(40, 39, 120)
6
__SplayNode(18, 13, 39)
4
__SplayNode(101, 39, 120)
5
[13, 18, 20, 30, 38, 39, 40, 101, 120]
9
[__SplayNode(101, 39, 120), __SplayNode(39, 18, 40), __SplayNode(18, 13, 30), __SplayNode(13, None, None)] 

[__SplayNode(101, 39, 120), __SplayNode(39, 18, 40), __SplayNode(18, 13, 30)] 

[__SplayNode(101, 39, 120), __SplayNode(39, 18, 40), __SplayNode(18, 13, 30), __SplayNode(30, 20, 38), __SplayNode(20, None, None)] 

[__SplayNode(101, 39, 120), __SplayNode(39, 18, 40), __SplayNode(18, 13, 30), __SplayNode(30, 20, 38)] 

[__SplayNode(101, 39, 120), __SplayNode(39, 18, 40), __SplayNode(18, 13, 30), __SplayNode(30, 20, 38), __SplayNode(38, None, None)] 

[__SplayNode(101, 39, 120), __SplayNode(39, 18, 40)] 

[__SplayNode(101, 39, 120), __SplayNode(39, 18, 40), __SplayNode(40, None, None)] 

[__SplayNode(101, 39, 120)] 

[__SplayNode(101, 39, 120), __SplayNode(120, None, None)] 

120
__SplayNode(120, 101, None)

#



你可能感兴趣的:(从头学数学,从头学数学)