Splaying Tree in Python

Splaying Tree 的实现。

采用top-down recursion进行splaying。插入和删除都用到了splaying。splaying只处理parent-children这种情况。对于zig-zig和zig-zag,处理两次parent children 即可。

这种做法我觉得是比较好的。因为到底只需要两种操作:rotateleft和rotateright。这样一来和avl又比较接近了。。

__author__ = 'bozeng'


## the fundamental operations are rotateleft and rotateright.

# it is always true for maybe both splaying tree and AVL tree. understand the recursive logic chain behind those operations.

class TreeNode:
    def __init__(self,key,value):
        self.key=key
        self.value=value
        self.left=None
        self.right=None


class SplayTree:
    def __init__(self):

        self.root=None

    def insert(self,key,value):

        if not self.root:
            self.root=TreeNode(key,value)
            return

        self.root=self.splaying(self.root,key)

        if key==self.root.key:
            self.root.value=value

        elif key<self.root.key:     ## so key's (supposed) parent was the current root. and it can very well have left and right subtrees.
            node=TreeNode(key,value)
            node.right=self.root    ## due to the properties of BST, those subtrees must be smaller than key (returned root must be the closest).
            node.left=self.root.left
            self.root.left=None
            self.root=node

        else:
            node=TreeNode(key,value)
            node.left=self.root
            node.right=self.root.right ## due to the properties of BST, those subtrees must be greater than key.
            self.root.right=None
            self.root=node


    def find(self,key):

        self.root=self.splaying(self.root,key)

        if self.root.key==key:
            return self.root.value

        return None


    def __contains__(self,key):

        return self.find(key)!=None



    def remove(self,key):

        if not self.root:
            print("empty tree")
            return

        self.root=self.splaying(self.root,key)

        if self.root.key!=key:
            return

        else:  # then we should delete the root

            # the traditional BST deletion is to swap with its inorder predecessor and delete recursively.

            if self.root.left==None:
                self.root=self.root.right

            else: # since now, every thing in the left subtree is smaller than key, everything right subtree larger.
                righttree=self.root.right
                # splaying up the largest element (closest to key) in the left subtree
                self.root=self.splaying(self.root.left,key)  # its right must be empty
                self.root.right=righttree

    # the purpose of splaying is to recursively:
    # move the node with key to root (of the subtree previously rooted at node). or, move the node before key
    # if key is not found to root of such.
    def splaying(self,node,key):

        if not node:
            return None

        if key==node.key:
            return node

        if key<node.key:
            if node.left==None:
                return node

            if key<node.left.key:
                node.left.left=self.splaying(node.left.left,key) # this is a grand parent situation now
                node=self.rotateRight(node)

            elif key>node.left.key:
                node.left.right=self.splaying(node.left.right,key)
                if node.left.right:
                    node.left=self.rotateLeft(node.left)

            if node.left:
                return self.rotateRight(node)

            return node


        elif key>node.key:
            if node.right==None:
                return node

            if key<node.right.key:
                node.right.left=self.splaying(node.right.left,key)
                if node.right.left:
                    node.right=self.rotateRight(node.right)

            elif key>node.right.key:
                node.right.right=self.splaying(node.right.right,key)
                node=self.rotateLeft(node)

            if node.right:
                return self.rotateLeft(node)

            return node


    def rotateLeft(self,node):  ## only deal with parent-child rotation
        if not node:
            return None

        child=node.right

        if not child:
            return node

        node.right=child.left
        child.left=node

        return child


    def rotateRight(self,node): ## only deal with parent-child rotation

        if not node:
            return None

        child=node.left

        if not child:
            return node

        node.left=child.right

        child.right=node

        return child

    def keys(self):

        def recursivePreorder(node):

            if not node:
                return

            yield node.key
            yield from recursivePreorder(node.left)
            yield from recursivePreorder(node.right)

        return recursivePreorder(self.root)


    def values(self):

        def recursivePreorder(node):
            if not node:
                return

            yield node.value

            yield from recursivePreorder(node.left)
            yield from recursivePreorder(node.right)

        return recursivePreorder(self.root)





splayTree=SplayTree()

splayTree.insert(12,'him')
splayTree.insert(10,'him2')
splayTree.insert(1,'him3')
splayTree.insert(3,'him4')
splayTree.insert(5,'him5')
splayTree.insert(100,'him6')

print(splayTree.find(3))

for x in splayTree.keys():
    print(x)



    原文作者:曾博
    原文地址: https://zhuanlan.zhihu.com/p/19958178
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞