Python에서 Red-Black 이진 트리 만들기
51385 단어 compscialgorithmspythonbinarytree
게시물Building a Red-Black Binary Tree in Python은 Qvault에 처음 등장했습니다.
레드 블랙 트리는 일종의 자체 균형 이진 검색 트리입니다. 각 노드는 여분의 비트를 저장하며 이를 색상(빨간색 또는 검은색)이라고 합니다. 색상은 삽입 및 삭제 중에 트리가 대략적으로 균형을 유지하도록 합니다. 나무가 수정되면 새 나무가 재정렬되고 최악의 경우 나무가 얼마나 불균형해질 수 있는지를 제한하는 색상 속성을 복원하기 위해 다시 칠해집니다.
레드-블랙 트리의 목적은 균형을 유지하여 조회 및 삭제와 같은 일반적인 작업이
O(n*log(n))
보다 악화되지 않도록 하는 것입니다.방해해서 미안해! 나는 당신이 나의 새로운 무료 Python 과정인 "Big-O Data Structures"를 확인해야 한다고 언급하고 싶었습니다. 다가오는 코딩 인터뷰와 화이트보드 세션을 끝내기 위해 알아야 할 모든 것을 배우게 될 것입니다.
Start Python Data Structures Course
균형 이진 트리란?
이진 트리에 색상을 추가하는 이유는 균형을 유지하기 위한 것이므로 이진 트리가 균형을 이루는 방법과 이유를 이해해야 합니다. 간단히 말해서, 균형잡힌 나무의 가지는 높이가 1개 이상 차이가 나지 않습니다.
다음 트리는 두 가지 사이에서 하나의 높이가 2이고 다른 하나의 높이가 3이기 때문에 균형을 이룹니다.
A
/ \
B C
/
D
다음 나무는 가지의 높이가 1 이상 다르기 때문에 균형이 맞지 않습니다.
C
의 오른쪽은 높이가 2이고 왼쪽은 높이가 4입니다.A
/ \
B C
/ /
D E
/
G
균형 잡힌 트리를 원하는 이유는 무엇입니까?
균형 잡힌 이진 검색 트리는 속도를 보장합니다. 이진 트리의 작업 속도는 트리의 높이에 따라 다릅니다. 트리가 균형을 이루면 높이가 노드 수의
log
에 불과하므로 트리가 최대한 빨리 작동합니다. 그러나 트리가 균형이 맞지 않는 경우(예: 하나의 매우 긴 가지) 높이는 로그가 아닌 총 노드 수 때문입니다.A
/
B
/
C
/
D
레드 블랙 트리의 속성
Binary Search Tree 의 모든 속성 외에도 레드-블랙 트리에는 다음이 있어야 합니다.
nil
리프 노드가 검은색입니다. nil
노드에 도달하기 위해 동일한 수의 검은색 노드를 통과합니다. Python에서 Red-Black 트리 구현
1단계 – RBNode 클래스
구현에서는
Tree
클래스와 Node
클래스를 사용합니다. 노드는 매우 간단할 것입니다. 단지 생성자일 뿐입니다.class RBNode:
def __init__ (self, val):
self.red = False
self.parent = None
self.val = val
self.left = None
self.right = None
<small id="shcb-language-1"><span>Code language:</span> <span>Python</span> <span>(</span><span>python</span><span>)</span></small>
2단계 – RBTree 클래스
다음으로 생성자로 트리 클래스를 만들어 봅시다.
class RBTree:
def __init__ (self):
self.nil = RBNode(0)
self.nil.red = False
self.nil.left = None
self.nil.right = None
self.root = self.nil`
<small id="shcb-language-2"><span>Code language:</span> <span>Python</span> <span>(</span><span>python</span><span>)</span></small>
3단계 – 방법 삽입
def insert(self, val):
# Ordinary Binary Search Insertion
new_node = RBNode(val)
new_node.parent = None
new_node.left = self.nil
new_node.right = self.nil
new_node.red = True # new node must be red
parent = None
current = self.root
while current != self.nil:
parent = current
if new_node.val < current.val:
current = current.left
elif new_node.val > current.val:
current = current.right
else:
return
# Set the parent and insert the new node
new_node.parent = parent
if parent == None:
self.root = new_node
elif new_node.val < parent.val:
parent.left = new_node
else:
parent.right = new_node
# Fix the tree
self.fix_insert(new_node)
<small id="shcb-language-3"><span>Code language:</span> <span>Python</span> <span>(</span><span>python</span><span>)</span></small>
삽입 방법은 전통적인 이진 트리 삽입 방법과 매우 유사합니다. 가장 큰 차이점은 삽입을 수행한 후 특수
fix_insert
메서드를 호출한다는 것입니다. 지금은 그냥 부르기만 하면 됩니다. 잠시 후에 구현하겠습니다.4단계 - 왼쪽으로 회전
다가오는 "수정"단계에서 몇 가지 회전 방법이 필요합니다. 이제 코드를 작성해 보겠습니다.
# rotate left at node x
def rotate_left(self, x):
y = x.right
x.right = y.left
if y.left != self.nil:
y.left.parent = x
y.parent = x.parent
if x.parent == None:
self.root = y
elif x == x.parent.left:
x.parent.left = y
else:
x.parent.right = y
y.left = x
x.parent = y
<small id="shcb-language-4"><span>Code language:</span> <span>Python</span> <span>(</span><span>python</span><span>)</span></small>
5단계 – 오른쪽으로 회전
# rotate right at node x
def rotate_right(self, x):
y = x.left
x.left = y.right
if y.right != self.nil:
y.right.parent = x
y.parent = x.parent
if x.parent == None:
self.root = y
elif x == x.parent.right:
x.parent.right = y
else:
x.parent.left = y
y.right = x
x.parent = y
<small id="shcb-language-5"><span>Code language:</span> <span>Python</span> <span>(</span><span>python</span><span>)</span></small>
6단계 - 인서트 수정
진정한 빵과 버터는 이 단계에 있습니다. 이것이 바로 레드-블랙 트리의 균형을 맞추는 것입니다.
def fix_insert(self, new_node):
while new_node != self.root and new_node.parent.red:
if new_node.parent == new_node.parent.parent.right:
u = new_node.parent.parent.left # uncle
if u.red:
u.red = False
new_node.parent.red = False
new_node.parent.parent.red = True
new_node = new_node.parent.parent
else:
if new_node == new_node.parent.left:
new_node = new_node.parent
self.rotate_right(new_node)
new_node.parent.red = False
new_node.parent.parent.red = True
self.rotate_left(new_node.parent.parent)
else:
u = new_node.parent.parent.right # uncle
if u.red:
u.red = False
new_node.parent.red = False
new_node.parent.parent.red = True
new_node = new_node.parent.parent
else:
if new_node == new_node.parent.right:
new_node = new_node.parent
self.rotate_left(new_node)
new_node.parent.red = False
new_node.parent.parent.red = True
self.rotate_right(new_node.parent.parent)
self.root.red = False
<small id="shcb-language-6"><span>Code language:</span> <span>Python</span> <span>(</span><span>python</span><span>)</span></small>
코드 내 Red-Black 트리의 전체 예
import random
class RBNode:
def __init__ (self, val):
self.red = False
self.parent = None
self.val = val
self.left = None
self.right = None
class RBTree:
def __init__ (self):
self.nil = RBNode(0)
self.nil.red = False
self.nil.left = None
self.nil.right = None
self.root = self.nil
def insert(self, val):
# Ordinary Binary Search Insertion
new_node = RBNode(val)
new_node.parent = None
new_node.left = self.nil
new_node.right = self.nil
new_node.red = True # new node must be red
parent = None
current = self.root
while current != self.nil:
parent = current
if new_node.val < current.val:
current = current.left
elif new_node.val > current.val:
current = current.right
else:
return
# Set the parent and insert the new node
new_node.parent = parent
if parent == None:
self.root = new_node
elif new_node.val < parent.val:
parent.left = new_node
else:
parent.right = new_node
# Fix the tree
self.fix_insert(new_node)
def fix_insert(self, new_node):
while new_node != self.root and new_node.parent.red:
if new_node.parent == new_node.parent.parent.right:
u = new_node.parent.parent.left # uncle
if u.red:
u.red = False
new_node.parent.red = False
new_node.parent.parent.red = True
new_node = new_node.parent.parent
else:
if new_node == new_node.parent.left:
new_node = new_node.parent
self.rotate_right(new_node)
new_node.parent.red = False
new_node.parent.parent.red = True
self.rotate_left(new_node.parent.parent)
else:
u = new_node.parent.parent.right # uncle
if u.red:
u.red = False
new_node.parent.red = False
new_node.parent.parent.red = True
new_node = new_node.parent.parent
else:
if new_node == new_node.parent.right:
new_node = new_node.parent
self.rotate_left(new_node)
new_node.parent.red = False
new_node.parent.parent.red = True
self.rotate_right(new_node.parent.parent)
self.root.red = False
def exists(self, val):
curr = self.root
while curr != self.nil and val != curr.val:
if val < curr.val:
curr = curr.left
else:
curr = curr.right
return curr
# rotate left at node x
def rotate_left(self, x):
y = x.right
x.right = y.left
if y.left != self.nil:
y.left.parent = x
y.parent = x.parent
if x.parent == None:
self.root = y
elif x == x.parent.left:
x.parent.left = y
else:
x.parent.right = y
y.left = x
x.parent = y
# rotate right at node x
def rotate_right(self, x):
y = x.left
x.left = y.right
if y.right != self.nil:
y.right.parent = x
y.parent = x.parent
if x.parent == None:
self.root = y
elif x == x.parent.right:
x.parent.right = y
else:
x.parent.left = y
y.right = x
x.parent = y
def __repr__ (self):
lines = []
print_tree(self.root, lines)
return '\n'.join(lines)
def print_tree(node, lines, level=0):
if node.val != 0:
print_tree(node.left, lines, level + 1)
lines.append('-' * 4 * level + '> ' +
str(node.val) + ' ' + ('r' if node.red else 'b'))
print_tree(node.right, lines, level + 1)
def get_nums(num):
random.seed(1)
nums = []
for _ in range(num):
nums.append(random.randint(1, num-1))
return nums
def main():
tree = RBTree()
for x in range(1, 51):
tree.insert(x)
print(tree)
main()
<small id="shcb-language-7"><span>Code language:</span> <span>Python</span> <span>(</span><span>python</span><span>)</span></small>
코딩할 준비가 되셨나요?
Try our coding courses free
Join our Discord community
질문이나 의견이 있으십니까?
질문이나 의견이 있으면 트위터에서 나를 팔로우하고 연락하십시오. 기사에서 실수를 한 경우 반드시 let me know 수정하여 수정할 수 있도록 해주세요!
Reference
이 문제에 관하여(Python에서 Red-Black 이진 트리 만들기), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/bootdotdev/building-a-red-black-binary-tree-in-python-208a텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)