【问题标题】:Deletion in binary search tree with parent pointers使用父指针删除二叉搜索树
【发布时间】:2012-07-09 09:57:11
【问题描述】:

我已经尝试解决在线挑战 9 天了。我有一个重复 100,000 次的在线插入删除,我需要找到其中的中位数。我尝试了两个堆,但实现随机删除不起作用。我现在开始使用二叉搜索树,因为它们似乎在 2 秒内在我的计算机上插入和删除了 100,000 个数据。我正在研究 python,我需要在 16 秒内运行。

我已经在线检查了解决方案,但完全不能满足我的需要。我发现在插入和删除时计算中位数可能是一个好策略。这我写了两个方法来获取节点的顺序后继或前驱。

问题是我认为是 - 在递归删除期间不正确地分配父指针。

我尝试了两种技术,但都效果不佳,如果我能得到一些帮助,我将不胜感激!

代码:

import sys
class BSTNode:
    def __init__(self,x,parent):
        self.data = x
        self.left = None
        self.right = None
        self.count = 1
        self.parent = parent

def delete(x,T):
    if T is None:
        print('Element Not Found')
    elif x<T.data:
        T.left = delete(x,T.left)
    elif x>T.data:
        T.right = delete(x,T.right)
    elif T.left and T.right:
        TempNode = findMin(T.right)
        T.data = TempNode.data
        T.right = delete(TempNode.data,T.right)
    else:
        if T.left is None:
            T = T.right
        elif T.right is None:
            T = T.left
    return T

def findMin(T):
    if T.left:
        return findMin(T.left)
    else:
        return T

def insert(x,T,parent=None):
    if T is None:
        T = BSTNode(x,parent)
    elif x<T.data:
        T.left = insert(x,T.left,T)
    elif x>T.data:
        T.right = insert(x,T.right,T)
    else:
        T.count = T.count + 1
    return T

def inorder(T):
    if T is None:
        return
    else:
        inorder(T.left)
        b = back(T)
        if b:
            print("back:",b.data)
        print(T.data)
        n = next(T)
        if n:
            print("next:",n.data)
        inorder(T.right)

def preorder(T,i=0):
    if T is None:
        return
    else:
        for j in range(i):
            sys.stdout.write("    ")
        print(T.data)
        preorder(T.left,i+1)
        preorder(T.right,i+1)

def next(node):
    if node is None:
        return
    if node.right:
        n = node.right
        while n.left:
            n = n.left
        return n
    else:
        n = node
        while n.parent and n.parent.right is n:
            n = n.parent
        if n.parent and n.parent.left is n:
            return n.parent
        else:
            return

def back(node):
    if node is None:
        return
    if node.left:
        n = node.left
        while n.right:
            n = n.right
        return n
    else:
        n = node
        while n.parent and n.parent.left is n:
            n = n.parent
        if n.parent and n.parent.right is n:
            return n.parent
        else:
            return

T = None
T = insert(7,T)
T = insert(4,T)
T = insert(2,T)
T = insert(1,T)

T = insert(13,T)
T = insert(15,T)
T = insert(16,T)
T = insert(6,T)

T = insert(5,T)
T = insert(3,T)
T = insert(11,T)
T = insert(14,T)

T = insert(12,T)
T = insert(9,T)
T = insert(8,T)
T = insert(10,T)

T = delete(11,T)
T = delete(12,T)
T = delete(13,T)
T = delete(8,T)
preorder(T)
inorder(T)

输出

7
    4
        2
            1
            3
        6
            5
    14
        9
            10
        15
            16
1
('next:', 2)
('back:', 1)
2
('next:', 3)
('back:', 2)
3
('next:', 4)
('back:', 3)
4
('next:', 5)
('back:', 4)
5
('next:', 6)
('back:', 5)
6
('next:', 7)
('back:', 6)
7
('next:', 9)
9
('next:', 10)
('back:', 9)
10
('next:', 12)
('back:', 10)
14
('next:', 15)
('back:', 14)
15
('next:', 16)
('back:', 15)
16

预期 - 9 的后面是 7

我的回答

def delete(x,T,parent=None):
    if T is None:
        print('Element Not Found')
    elif x<T.data:
        T.left = delete(x,T.left,T)
    elif x>T.data:
        T.right = delete(x,T.right,T)
    elif T.count==1:
        # 2 CHILDREN
        if T.left and T.right:
            TempNode = findMin(T.right)
            T.data = TempNode.data
            T.right = delete(TempNode.data,T.right,T)
        # 0 CHILDREN
        elif T.left is None and T.right is None:
            T = None
        # 1 CHILDREN
        elif T.right is not None:
            T = T.right
            T.parent = parent
        elif T.left is not None:
            T = T.left
            T.parent = parent
    else:
        T.count = T.count - 1
    return T

现在

9
    4
        2
            1
            3
        5
    14
        10
        15
            16
1 (2) 
('next:', 2)
('back:', 1)
2 (4) 
('next:', 3)
('back:', 2)
3 (2) 
('next:', 4)
('back:', 3)
4 (9) 
('next:', 5)
('back:', 4)
5 (4) 
('next:', 9)
('back:', 5)
9  
('next:', 10)
('back:', 9)
10 (14) 
('next:', 14)
('back:', 10)
14 (9) 
('next:', 15)
('back:', 14)
15 (14) 
('next:', 16)
('back:', 15)
16 (15)

【问题讨论】:

  • 你需要为这个挑战做些什么?如果不进行平衡,二叉搜索树将退化为随机插入和删除的链表。
  • 伟大的力量知道!这可能需要花费一生的时间才能弄清楚……我确实想接下来平衡它,我找不到任何合适的资源,我的文字艾伦韦斯只有插入过程中的平衡理论!蹩脚的借口!如果你知道更好的资源,请告诉我,谢谢
  • 我的直觉是你可以用Python内置的set解决你的问题,不需要自己实现。正确实现平衡树可能非常棘手......所以更多关于你想要实现的细节会很好;)
  • 哦!!!如果 python 有一个平衡的 bst 会很棒,我认为它很有用...我试图找到 100,000 个元素的中值,每次找到中值后这些元素被一个接一个地插入。我实施和使用 bst 来最好地插入和删除那个数量和那个频繁的数据。我为中位数保留最多两个指针,并在插入或删除的新元素落在​​左侧或右侧时不断更新它们。我从这些指针中获取中位数以在插入/删除后打印中位数,这是我的挑战
  • 你可以试试blist。如果您不能使用自己的模块,您可以尝试从 blist 的源代码中复制粘贴相关代码。

标签: python tree binary-search-tree parent


【解决方案1】:

您似乎没有在delete(x,T): 例程的else: 部分中的T = T.rightT = T.left 之后更新T 的父指针。另一种选择可能是在替换左子或右子时更新父指针。我认为在整个代码中始终遵循这两种约定中的任何一种都可以解决您的问题。

【讨论】:

  • 你的意思是 T = T.right 现在 T 变成 T.right 所以 T.parent 需要更新。这正是我想出递归做的......谢谢
  • 啊,它的你!是的,试过了,似乎有效..在考虑递归方式之前有问题......谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-18
相关资源
最近更新 更多