ツリー(Tree)(2)
38796 ワード
バイナリナビゲーションツリーの削除
Leafノードの削除
Leaf Node(=Terminal Node)
:サブノードのないノード
サブノードがあるノードを削除

2つのサブノードを持つノードを削除

第1の方法の順序
バイナリ・ナビゲーション・ツリーの削除の実装
削除するノードのナビゲート
def deleteNodeSearch(self, value):
searched = False
self.current_node = self.head
self.parent_node = self.head
while self.current_node:
if self.current_node.value == value:
searched = True
break
elif self.current_node.value > value:
self.parent_node = self.current_node
self.current_node = self.current_node.left
else:
self.parent_node = self.current_node
self.current_node = self.current_node.right
if searched == False:
return False
else:
return self.current_node, self.parent_node
削除するノードはLeafノードです。

current_node
:削除するノードparent_node
:削除するノードの親def deleteNode(self, value):
self.current_node, self.parent_node = self.deleteNodeSearch(value)
# 삭제할 노드가 Leaf Node인 경우
if self.current_node.left == None and self.current_node.right == None:
# 삭제할 노드가 부모 노드의 왼쪽에 있는 경우, 오른쪽에 있는 경우
if self.parent_node.value > value:
self.parent_node.left = None
else:
self.parent_node.right = None
削除するノードがサブノードが1つしかない場合。

# 삭제할 노드의 자식 노드가 1개인 경우
if self.current_node.left != None and self.current_node.right == None:
if self.parent_node.value > value:
self.parent_node.left = self.current_node.left
else:
self.parent_node.right = self.current_node.left
elif self.current_node.left == None and self.current_node.right != None:
if self.parent_node.value > value:
self.parent_node.left = self.current_node.right
else:
self.parent_node.right = self.current_node.right
削除するノードにサブノードが2つある場合。
削除するノードが親ノードの左側にある場合。

# 삭제할 노드의 자식 노드가 2개인 경우
if self.current_node.left != None and self.current_node.right != None:
# 가장 작은 값을 가진 노드와 그 노드의 부모 노드
self.change_node = self.current_node.right
self.change_node_parent = self.current_node.right
while self.change_node.left != None:
self.change_node_parent = self.change_node
self.change_node = self.change_node.left
# 삭제할 노드가 왼쪽에 있는 경우
if self.parent_node.value > value:
# 가장 작은 값을 가진 노드가 오른쪽 자식 노드를 가진 경우
if self.change_node.right != None:
self.change_node_parent.left = self.change_node.right
else:
self.change_node_parent.left = None
self.parent_node.left = self.change_node
self.change_node.left = self.current_node.left
self.change_node.right = self.current_node.right
削除するノードが親ノードの右側にある場合。

# 삭제할 노드가 오른쪽에 있는 경우
else:
if self.change_node.right != None:
self.change_node_parent.left = self.change_node.right
else:
self.change_node_parent.left = None
self.parent_node.right = self.change_node
self.change_node.left = self.current_node.left
self.change_node.right = self.current_node.right
完全なコード実装 class Node:
def __init__(self, value):
# head, left, right는 노드의 주소를 가리키는 변수이다.
self.value = value
self.left = None
self.right = None
class BinarySearchTree:
def __init__(self, head):
# head는 루트노드의 주소를 가진다.
self.head = head
def insertNode(self, value):
# 트리를 순회하며 값을 삽입해야하기 때문에 임의 변수를 선언한다.
self.current_node = self.head
while True:
if self.current_node.value > value:
if self.current_node.left != None:
self.current_node = self.current_node.left
else:
self.current_node.left = Node(value)
break
else:
if self.current_node.right != None:
self.current_node = self.current_node.right
else:
self.current_node.right = Node(value)
break
def searchNode(self, value):
self.current_node = self.head
while self.current_node:
if self.current_node.value == value:
return True
elif self.current_node.value > value:
self.current_node = self.current_node.left
else:
self.current_node = self.current_node.right
return False
def deleteNodeSearch(self, value):
searched = False
self.current_node = self.head
self.parent_node = self.head
while self.current_node:
if self.current_node.value == value:
searched = True
break
elif self.current_node.value > value:
self.parent_node = self.current_node
self.current_node = self.current_node.left
else:
self.parent_node = self.current_node
self.current_node = self.current_node.right
if searched == False:
return False
else:
return self.current_node, self.parent_node
def deleteNode(self, value):
self.current_node, self.parent_node = self.deleteNodeSearch(value)
# 삭제할 노드가 Leaf Node인 경우
if self.current_node.left == None and self.current_node.right == None:
# 삭제할 노드가 부모 노드의 왼쪽에 있는 경우, 오른쪽에 있는 경우
if self.parent_node.value > value:
self.parent_node.left = None
else:
self.parent_node.right = None
# 삭제할 노드의 자식 노드가 1개인 경우
if self.current_node.left != None and self.current_node.right == None:
if self.parent_node.value > value:
self.parent_node.left = self.current_node.left
else:
self.parent_node.right = self.current_node.left
elif self.current_node.left == None and self.current_node.right != None:
if self.parent_node.value > value:
self.parent_node.left = self.current_node.right
else:
self.parent_node.right = self.current_node.right
# 삭제할 노드의 자식 노드가 2개인 경우
if self.current_node.left != None and self.current_node.right != None:
# 가장 작은 값을 가진 노드와 그 노드의 부모 노드
self.change_node = self.current_node.right
self.change_node_parent = self.current_node.right
while self.change_node.left != None:
self.change_node_parent = self.change_node
self.change_node = self.change_node.left
# 삭제할 노드가 왼쪽에 있는 경우
if self.parent_node.value > value:
# 가장 작은 값을 가진 노드가 오른쪽 자식 노드를 가진 경우
if self.change_node.right != None:
self.change_node_parent.left = self.change_node.right
else:
self.change_node_parent.left = None
self.parent_node.left = self.change_node
self.change_node.left = self.current_node.left
self.change_node.right = self.current_node.right
# 삭제할 노드가 오른쪽에 있는 경우
else:
if self.change_node.right != None:
self.change_node_parent.left = self.change_node.right
else:
self.change_node_parent.left = None
self.parent_node.right = self.change_node
self.change_node.left = self.current_node.left
self.change_node.right = self.current_node.right
del self.current_node
return True
すべてのコードをテスト
import random
# 0 ~ 999 중, 100 개의 숫자 랜덤 선택
bst_nums = set()
while len(bst_nums) != 100:
bst_nums.add(random.randint(0, 999))
# print (bst_nums)
# 선택된 100개의 숫자를 이진 탐색 트리에 입력, 임의로 루트노드는 500을 넣기로 함
head = Node(500)
binary_tree = BinarySearchTree(head)
for num in bst_nums:
binary_tree.insertNode(num)
# 입력한 100개의 숫자 검색 (검색 기능 확인)
for num in bst_nums:
if binary_tree.searchNode(num) == False:
print ('search failed', num)
# 입력한 100개의 숫자 중 10개의 숫자를 랜덤 선택
delete_nums = set()
bst_nums = list(bst_nums)
while len(delete_nums) != 10:
delete_nums.add(bst_nums[random.randint(0, 99)])
# 선택한 10개의 숫자를 삭제 (삭제 기능 확인)
for del_num in delete_nums:
if binary_tree.deleteNode(del_num) == False:
print('delete failed', del_num)
# 출력 없음
Reference
この問題について(ツリー(Tree)(2)), 我々は、より多くの情報をここで見つけました
https://velog.io/@zz1996zz/트리Tree-2
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
class Node:
def __init__(self, value):
# head, left, right는 노드의 주소를 가리키는 변수이다.
self.value = value
self.left = None
self.right = None
class BinarySearchTree:
def __init__(self, head):
# head는 루트노드의 주소를 가진다.
self.head = head
def insertNode(self, value):
# 트리를 순회하며 값을 삽입해야하기 때문에 임의 변수를 선언한다.
self.current_node = self.head
while True:
if self.current_node.value > value:
if self.current_node.left != None:
self.current_node = self.current_node.left
else:
self.current_node.left = Node(value)
break
else:
if self.current_node.right != None:
self.current_node = self.current_node.right
else:
self.current_node.right = Node(value)
break
def searchNode(self, value):
self.current_node = self.head
while self.current_node:
if self.current_node.value == value:
return True
elif self.current_node.value > value:
self.current_node = self.current_node.left
else:
self.current_node = self.current_node.right
return False
def deleteNodeSearch(self, value):
searched = False
self.current_node = self.head
self.parent_node = self.head
while self.current_node:
if self.current_node.value == value:
searched = True
break
elif self.current_node.value > value:
self.parent_node = self.current_node
self.current_node = self.current_node.left
else:
self.parent_node = self.current_node
self.current_node = self.current_node.right
if searched == False:
return False
else:
return self.current_node, self.parent_node
def deleteNode(self, value):
self.current_node, self.parent_node = self.deleteNodeSearch(value)
# 삭제할 노드가 Leaf Node인 경우
if self.current_node.left == None and self.current_node.right == None:
# 삭제할 노드가 부모 노드의 왼쪽에 있는 경우, 오른쪽에 있는 경우
if self.parent_node.value > value:
self.parent_node.left = None
else:
self.parent_node.right = None
# 삭제할 노드의 자식 노드가 1개인 경우
if self.current_node.left != None and self.current_node.right == None:
if self.parent_node.value > value:
self.parent_node.left = self.current_node.left
else:
self.parent_node.right = self.current_node.left
elif self.current_node.left == None and self.current_node.right != None:
if self.parent_node.value > value:
self.parent_node.left = self.current_node.right
else:
self.parent_node.right = self.current_node.right
# 삭제할 노드의 자식 노드가 2개인 경우
if self.current_node.left != None and self.current_node.right != None:
# 가장 작은 값을 가진 노드와 그 노드의 부모 노드
self.change_node = self.current_node.right
self.change_node_parent = self.current_node.right
while self.change_node.left != None:
self.change_node_parent = self.change_node
self.change_node = self.change_node.left
# 삭제할 노드가 왼쪽에 있는 경우
if self.parent_node.value > value:
# 가장 작은 값을 가진 노드가 오른쪽 자식 노드를 가진 경우
if self.change_node.right != None:
self.change_node_parent.left = self.change_node.right
else:
self.change_node_parent.left = None
self.parent_node.left = self.change_node
self.change_node.left = self.current_node.left
self.change_node.right = self.current_node.right
# 삭제할 노드가 오른쪽에 있는 경우
else:
if self.change_node.right != None:
self.change_node_parent.left = self.change_node.right
else:
self.change_node_parent.left = None
self.parent_node.right = self.change_node
self.change_node.left = self.current_node.left
self.change_node.right = self.current_node.right
del self.current_node
return True
import random
# 0 ~ 999 중, 100 개의 숫자 랜덤 선택
bst_nums = set()
while len(bst_nums) != 100:
bst_nums.add(random.randint(0, 999))
# print (bst_nums)
# 선택된 100개의 숫자를 이진 탐색 트리에 입력, 임의로 루트노드는 500을 넣기로 함
head = Node(500)
binary_tree = BinarySearchTree(head)
for num in bst_nums:
binary_tree.insertNode(num)
# 입력한 100개의 숫자 검색 (검색 기능 확인)
for num in bst_nums:
if binary_tree.searchNode(num) == False:
print ('search failed', num)
# 입력한 100개의 숫자 중 10개의 숫자를 랜덤 선택
delete_nums = set()
bst_nums = list(bst_nums)
while len(delete_nums) != 10:
delete_nums.add(bst_nums[random.randint(0, 99)])
# 선택한 10개의 숫자를 삭제 (삭제 기능 확인)
for del_num in delete_nums:
if binary_tree.deleteNode(del_num) == False:
print('delete failed', del_num)
# 출력 없음
Reference
この問題について(ツリー(Tree)(2)), 我々は、より多くの情報をここで見つけました https://velog.io/@zz1996zz/트리Tree-2テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol