欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python3 数据结构和算法(3) 二叉搜索树

程序员文章站 2024-03-16 16:27:34
...
import random
import time
from functools import wraps

def timethis(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        elapsed = time.time() - start
        print('%-30s %10s %f' % (func.__name__, ' cost time:', elapsed))
        return result
    return wrapper

class BSTNode():
    def __init__(self, k):
        self.key = k
        self.left = None
        self.right = None
        self.parent = None

    def __str__(self):
        return str(self.key)

class BinarySearchTree():
    def __init__(self):
        self.root = None

    def insert(self, k):
        n = BSTNode(k)
        current = self.root
        parent = None

        while current:
            parent = current
            if k < current.key:
                current = current.left
            else:
                current = current.right

        n.parent = parent
        if not parent:
            self.root = n
        else:
            if k < parent.key:
                parent.left = n
            else:
                parent.right = n

    def inorder_rec(self, node, keys):
        if node:
            self.inorder_rec(node.left, keys)
            keys.append(node.key)
            self.inorder_rec(node.right, keys)

    def inorder(self):
        keys = []
        self.inorder_rec(self.root, keys)
        return keys

    def search(self, k):
        p = self.root
        while p and p.key != k:
            if k < p.key:
                p = p.left
            else:
                p = p.right
        return p

    def minimum(self, node):
        while node.left:
            node = node.left
        return node

    def successor(self, node):
        if node.right:
            return self.minimum(node.right)

        p = node.parent
        while p and node == p.right:
            node = p
            p = p.parent
        return p

    def delete(self, node):
        x = y = None
        if node.left is None or node.right is None:
            y = node
        else:
            y = self.successor(node)

        if y.left is not None:
            x = y.left
        else:
            x = y.right

        if x is not None:
            x.parent = y.parent

        if y.parent is None:
            self.root = x
        else:
            if y == y.parent.left:
                y.parent.left = x
            else:
                y.parent.right = x

        if y != node:
            node.key = y.key


def test_insert(bst):
    for i in range(100):
        k = random.randint(1, 1000)
        if bst.search(k) is None:
            bst.insert(k)

    keys = bst.inorder()
    print(keys)
    s = sorted(keys)
    if s != keys:
        print('error')

def test_search(bst):
    for i in range(10):
        k = random.randint(1, 1000)
        node = bst.search(k)
        if node:
            print(k, 'in tree', node.key)
        else:
            print(k, 'not in tree')

    keys = bst.inorder()
    for i in range(10):
        k = keys[i]
        node = bst.search(k)
        if node:
            print(k, 'in tree', node.key)
        else:
            print(k, 'not in tree')

def test_delete(bst):
    deleted = 0
    while deleted < 10:
        k = random.randint(1, 1000)
        node = bst.search(k)
        if node:
            print('delete node', k)
            bst.delete(node)
            node = bst.search(k)
            if node:
                print('error, should not in tree any more')
                return

            keys = bst.inorder()
            s = sorted(keys)
            if s != keys:
                print('error not sorted after delete node')
            deleted += 1

    # delete all
    keys = bst.inorder()
    for i in range(len(keys)):
        j = random.randint(0, len(keys)-1)
        k = keys[j]
        node = bst.search(k)
        if not node:
            print('error, should in tree')
            return

        print('delete node', k)
        bst.delete(node)
        node = bst.search(k)
        if node:
            print('error, should not in tree any more')
            return

        keys = bst.inorder()
        s = sorted(keys)
        if s != keys:
            print('error not sorted after delete node')


def main():
    bst = BinarySearchTree()
    test_insert(bst)
    test_search(bst)
    test_delete(bst)


if __name__ == '__main__':
    main()