Skip to content

Commit 1fedce4

Browse files
feat(data_structures/binary_tree): add Splay Tree implementation
1 parent e2a78d4 commit 1fedce4

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
"""
2+
Splay Tree implementation in Python.
3+
4+
A Splay Tree is a self-adjusting binary search tree that brings the most
5+
recently accessed element to the root via tree rotations. It provides
6+
amortized O(log n) time complexity for search, insert, and delete operations.
7+
8+
Reference:
9+
https://en.wikipedia.org/wiki/Splay_tree
10+
"""
11+
12+
from __future__ import annotations
13+
from typing import Optional, List
14+
15+
16+
class Node:
17+
"""Node class for the Splay Tree."""
18+
19+
def __init__(self, key: int) -> None:
20+
self.key = key
21+
self.left: Optional[Node] = None
22+
self.right: Optional[Node] = None
23+
24+
25+
class SplayTree:
26+
"""Splay Tree Data Structure."""
27+
28+
def __init__(self) -> None:
29+
self.root: Optional[Node] = None
30+
31+
# ------------------------- ROTATIONS -------------------------
32+
def _right_rotate(self, x: Node) -> Node:
33+
y = x.left
34+
x.left = y.right
35+
y.right = x
36+
return y
37+
38+
def _left_rotate(self, x: Node) -> Node:
39+
y = x.right
40+
x.right = y.left
41+
y.left = x
42+
return y
43+
44+
# ------------------------- SPLAY OPERATION -------------------------
45+
def _splay(self, root: Optional[Node], key: int) -> Optional[Node]:
46+
if root is None or root.key == key:
47+
return root
48+
49+
# Key in left subtree
50+
if key < root.key:
51+
if root.left is None:
52+
return root
53+
54+
# Zig-Zig (Left Left)
55+
if key < root.left.key:
56+
root.left.left = self._splay(root.left.left, key)
57+
root = self._right_rotate(root)
58+
# Zig-Zag (Left Right)
59+
elif key > root.left.key:
60+
root.left.right = self._splay(root.left.right, key)
61+
if root.left.right:
62+
root.left = self._left_rotate(root.left)
63+
return root if root.left is None else self._right_rotate(root)
64+
65+
# Key in right subtree
66+
else:
67+
if root.right is None:
68+
return root
69+
70+
# Zig-Zig (Right Right)
71+
if key > root.right.key:
72+
root.right.right = self._splay(root.right.right, key)
73+
root = self._left_rotate(root)
74+
# Zig-Zag (Right Left)
75+
elif key < root.right.key:
76+
root.right.left = self._splay(root.right.left, key)
77+
if root.right.left:
78+
root.right = self._right_rotate(root.right)
79+
return root if root.right is None else self._left_rotate(root)
80+
81+
# ------------------------- INSERTION -------------------------
82+
def insert(self, key: int) -> None:
83+
"""Inserts a key into the Splay Tree."""
84+
if self.root is None:
85+
self.root = Node(key)
86+
return
87+
88+
self.root = self._splay(self.root, key)
89+
if self.root.key == key:
90+
return # No duplicates
91+
92+
new_node = Node(key)
93+
if key < self.root.key:
94+
new_node.right = self.root
95+
new_node.left = self.root.left
96+
self.root.left = None
97+
else:
98+
new_node.left = self.root
99+
new_node.right = self.root.right
100+
self.root.right = None
101+
self.root = new_node
102+
103+
# ------------------------- SEARCH -------------------------
104+
def search(self, key: int) -> bool:
105+
"""Searches for a key and splays it to the root."""
106+
self.root = self._splay(self.root, key)
107+
return self.root is not None and self.root.key == key
108+
109+
# ------------------------- DELETION -------------------------
110+
def delete(self, key: int) -> None:
111+
"""Deletes a key from the Splay Tree."""
112+
if not self.root:
113+
return
114+
115+
self.root = self._splay(self.root, key)
116+
if self.root.key != key:
117+
return # Key not found
118+
119+
if self.root.left is None:
120+
self.root = self.root.right
121+
else:
122+
temp = self.root.right
123+
self.root = self._splay(self.root.left, key)
124+
self.root.right = temp
125+
126+
# ------------------------- TRAVERSALS -------------------------
127+
def inorder(self, root: Optional[Node]) -> List[int]:
128+
"""Returns an inorder traversal of the tree."""
129+
return [] if not root else self.inorder(root.left) + [root.key] + self.inorder(root.right)
130+
131+
def preorder(self, root: Optional[Node]) -> List[int]:
132+
"""Returns a preorder traversal of the tree."""
133+
return [] if not root else [root.key] + self.preorder(root.left) + self.preorder(root.right)
134+
135+
136+
if __name__ == "__main__":
137+
# Example usage and demonstration
138+
tree = SplayTree()
139+
for value in [10, 20, 30, 40, 50, 25]:
140+
tree.insert(value)
141+
142+
print("Inorder traversal:", tree.inorder(tree.root))
143+
print("Search for 25:", tree.search(25))
144+
print("After searching 25, root =", tree.root.key)
145+
tree.delete(20)
146+
print("After deleting 20:", tree.inorder(tree.root))

0 commit comments

Comments
 (0)