forked from turkdogan/binarytree
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtree.py
99 lines (82 loc) · 2.49 KB
/
tree.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class Node(object):
"""docstring for Node"""
def __init__(self, key, value=None):
super(Node, self).__init__()
self.left = [None]
self.right = [None]
self.key = key
self.value = value
def __str__(self):
return str(self.key)
def deref(ref):
return ref[0]
def setref(ref, val):
ref[0] = val
class Tree(object):
"""docstring for Tree"""
def __init__(self):
super(Tree, self).__init__()
self.root = [None]
# Since Python doesn't support tail-call optimization, I think
# it is better to insert iteratively.
def insert(self, key, value=None):
curr = self.root
while True:
if deref(curr) is None:
setref(curr, Node(key, value))
break
if key < deref(curr).key:
curr = deref(curr).left
else:
curr = deref(curr).right
def remove(self, key):
node = self._find(key)
self._remove(node)
def find(self, key):
return deref(self._find(key)).value
def traverse_inorder(self, fn):
stack = []
curr = deref(self.root)
while True:
while curr:
stack.append(curr)
curr = deref(curr.left)
if stack:
curr = stack.pop()
fn(curr.key)
curr = deref(curr.right)
else:
break
def _remove(self, node):
left = deref(deref(node).left)
right = deref(deref(node).right)
# has two children
if left and right:
succ = self._find_successor(node)
deref(node).key = deref(succ).key
setref(succ, deref(succ).right[0])
# doesn't have any children
elif not left and not right:
setref(node, None)
# has one child
else:
n = deref(node)
n = n.left if deref(n.left) else n.right
setref(node, deref(n))
def _find_successor(self, node):
n = deref(node).right
while deref(n).left[0]:
n = deref(n).left
return n
def _find(self, key):
curr = self.root
while deref(curr):
if key < deref(curr).key:
curr = deref(curr).left
elif key > deref(curr).key:
curr = deref(curr).right
else:
return curr
raise KeyError('{0}'.format(key))