在Python中的AVL树中,有些节点无法删除。

huangapple go评论89阅读模式
英文:

Some nodes not being able to delete in AVL Tree in Python

问题

在删除AVL树中的节点时,只有特定的节点能够成功删除,当尝试删除其他节点时会出现AttributeError错误。以下是修复代码的建议:

首先,你的代码中存在一些 HTML 实体字符,如 "<" 和 ">",这些应该替换为 "<" 和 ">",以使代码正常运行。

其次,你在 delete_data 方法中的代码可能会导致错误,因为在 Python 中,无法将根节点设为 None,而应该返回新的根节点。下面是修改后的 delete_data 方法:

  1. def delete_data(self, root_node, data):
  2. if not root_node:
  3. return root_node
  4. if data < root_node.data:
  5. root_node.left = self.delete_data(root_node.left, data)
  6. elif data > root_node.data:
  7. root_node.right = self.delete_data(root_node.right, data)
  8. else:
  9. if not root_node.left:
  10. return root_node.right
  11. elif not root_node.right:
  12. return root_node.left
  13. temp = self.get_min(root_node.right)
  14. root_node.data = temp.data
  15. root_node.right = self.delete_data(root_node.right, temp.data)
  16. root_node.height = 1 + max(self.get_height(root_node.left), self.get_height(root_node.right))
  17. balance = self.get_balance(root_node)
  18. # Left - Left condition
  19. if balance > 1 and self.get_balance(root_node.left) >= 0:
  20. return self.rotate_right(root_node)
  21. # Left - Right condition
  22. if balance > 1 and self.get_balance(root_node.left) < 0:
  23. root_node.left = self.rotate_left(root_node.left)
  24. return self.rotate_right(root_node)
  25. # Right - Right condition
  26. if balance < -1 and self.get_balance(root_node.right) <= 0:
  27. return self.rotate_left(root_node)
  28. # Right - Left condition
  29. if balance < -1 and self.get_balance(root_node.right) > 0:
  30. root_node.right = self.rotate_right(root_node.right)
  31. return self.rotate_left(root_node)
  32. return root_node

以上是修复 delete_data 方法的建议,这应该可以解决你遇到的 AttributeError 问题。希望这对你有帮助!如果你还有其他问题,请随时提出。

英文:

When deleting nodes from my AVL Tree, only certain nodes are able to get deleted and when I delete those other nodes, I get AttributeError.

  1. from collections import deque
  2. class AVL_Tree:
  3. def __init__(self, data):
  4. self.data = data
  5. self.left = None
  6. self.right = None
  7. self.height = 1
  8. def levelOrder_Traversal(self, root_node):
  9. if not root_node:
  10. return
  11. else:
  12. q = deque()
  13. q.append(root_node)
  14. while len(q) &gt; 0:
  15. node = q.popleft()
  16. print(node.data)
  17. if node.left:
  18. q.append(node.left)
  19. if node.right:
  20. q.append(node.right)
  21. def get_height(self, root_node):
  22. if not root_node:
  23. return 0
  24. else: return root_node.height
  25. def get_balance(self, root_node):
  26. if not root_node:
  27. return 0
  28. else:
  29. return self.get_height(root_node.left) - self.get_height(root_node.right)
  30. def rotate_right(self, node):
  31. new_root = node.left
  32. node.left = new_root.right
  33. new_root.right = node
  34. node.height = 1 + max(self.get_height(node.left), self.get_height(node.right))
  35. new_root.height = 1 + max(self.get_height(new_root.left), self.get_height(new_root.right))
  36. return new_root
  37. def rotate_left(self, node):
  38. new_root = node.right
  39. node.right = new_root.left
  40. new_root.left = node
  41. node.height = 1 + max(self.get_height(node.left), self.get_height(node.right))
  42. new_root.height = 1 + max(self.get_height(new_root.left), self.get_height(new_root.right))
  43. return new_root
  44. def insert_data(self, root_node, new_data):
  45. if not root_node:
  46. return AVL_Tree(new_data)
  47. elif new_data &lt; root_node.data:
  48. root_node.left = self.insert_data(root_node.left, new_data)
  49. else:
  50. root_node.right = self.insert_data(root_node.right, new_data)
  51. root_node.height = 1 + max(self.get_height(root_node.left), self.get_height(root_node.right))
  52. balance = self.get_balance(root_node)
  53. # left - left condition
  54. if balance &gt; 1 and new_data &lt; root_node.left.data:
  55. return self.rotate_right(root_node)
  56. # left - right condition
  57. if balance &gt; 1 and new_data &gt; root_node.left.data:
  58. root_node.left = self.rotate_left(root_node.left)
  59. return self.rotate_right(root_node)
  60. # right - right condition
  61. if balance &lt; -1 and new_data &gt; root_node.right.data:
  62. return self.rotate_left(root_node)
  63. # right - left condition
  64. if balance &lt; -1 and new_data &lt; root_node.right.data:
  65. root_node.right = self.rotate_right(root_node.right)
  66. return self.rotate_left(root_node)
  67. return root_node
  68. def get_min(self, root_node):
  69. current = root_node
  70. while current:
  71. current = current.left
  72. return current
  73. def delete_data(self, root_node, data):
  74. if not root_node:
  75. return root_node
  76. if data &lt; root_node.data:
  77. root_node.left = self.delete_data(root_node.left, data)
  78. elif data &gt; root_node.data:
  79. root_node.right = self.delete_data(root_node.right, data)
  80. else:
  81. if not root_node.left:
  82. temp = root_node.right
  83. root_node = None
  84. return temp
  85. elif not root_node.right:
  86. temp = root_node.left
  87. root_node = None
  88. return temp
  89. temp = self.get_min(root_node.right)
  90. root_node.data = temp.data
  91. root_node.right = self.delete_data(root_node.right, temp.data)
  92. root_node.height = 1 + max(self.get_height(root_node.left), self.get_height(root_node.right))
  93. balance = self.get_balance(root_node)
  94. # Left - Left condition
  95. if balance &gt; 1 and self.get_balance(root_node.left) &gt;= 0:
  96. return self.rotate_right(root_node)
  97. # Left - Right condition
  98. if balance &gt; 1 and self.get_balance(root_node.left) &lt; 0:
  99. root_node.left = self.rotate_left(root_node.left)
  100. return self.rotate_right(root_node)
  101. # Right - Right condition
  102. if balance &lt; -1 and self.get_balance(root_node.right) &lt;= 0:
  103. return self.rotate_left(root_node)
  104. # Right - Left condition
  105. if balance &lt; -1 and self.get_balance(root_node.right) &gt; 0:
  106. root_node.right = self.rotate_right(root_node.right)
  107. return self.rotate_left(root_node)
  108. return root_node
  109. avl = AVL_Tree(30)
  110. avl = avl.insert_data(avl, 25)
  111. avl = avl.insert_data(avl, 35)
  112. avl = avl.insert_data(avl, 20)
  113. avl = avl.insert_data(avl, 15)
  114. avl = avl.insert_data(avl, 5)
  115. avl = avl.insert_data(avl, 10)
  116. avl = avl.insert_data(avl, 50)
  117. avl = avl.insert_data(avl, 60)
  118. avl = avl.insert_data(avl, 70)
  119. avl = avl.insert_data(avl, 65)
  120. print(&quot;AVL Tree before deletion:&quot;)
  121. avl.levelOrder_Traversal(avl)
  122. print(&quot;\nAVL Tree after deleting data:&quot;)
  123. avl = avl.delete_data(avl, 30)
  124. avl.levelOrder_Traversal(avl)

In those nodes [ 20, 10, 50, 5, 15, 30, 65, 25, 35, 60, 70 ],
[ 20, 10, 50, 30, 65 ] ---> these five nodes raise AttributeError when I try to delete them.

I am self-studying data structures so I have no mentors or teachers to ask when I have problems. I tried chatgpt and google but I can't find answer for specific questions like this. So, I'm here asking for how I should fix my code.

I'd really appreciate if you guys can help me out. Thanks a lot!!!

答案1

得分: 1

问题出在你的get_min方法上:它返回了你要查找的节点的左子节点,但是它是空的!你可以非常简单地修复它:

  1. def get_min(self, root_node):
  2. current = root_node
  3. while current.left:
  4. current = current.left
  5. return current

通过这个修复,30节点将被正确删除,并且生成的树的遍历是正确的:

  1. 20 , 10 50, 5 15 35 65, - - - - 25 - 60 70

(-添加以更好地看到树的结构)

英文:

The problem comes for your get_min method: it returns the left child of the node you seek, which is None! You can fix it very simply:

  1. def get_min(self, root_node):
  2. current = root_node
  3. while current.left:
  4. current = current.left
  5. return current

With this fix, the 30 node is correctly deleted, and the traversal of the resulting tree is correct:

  1. 20 , 10 50, 5 15 35 65, - - - - 25 - 60 70

(- added to better see the tree structure)

huangapple
  • 本文由 发表于 2023年7月20日 21:08:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76730248.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定