diff --git a/__main__.py b/__main__.py
index dd894ceb9a920d3514fcf75166c168440fa3d316..b542589fb4f6b0342676d431cef25d9620645a3b 100644
--- a/__main__.py
+++ b/__main__.py
@@ -1,15 +1,5 @@
 import random
 
-from numpy import sort
-
-
-class Node:
-    def __init__(self, order):
-        self.order = order
-        self.is_leaf = True
-        self.keys = []
-        self.children = []
-
 
 def lower_bound(array, value):
     low = 0
@@ -45,12 +35,40 @@ def is_value_in_array(array, value):
     return False
 
 
+def find_value_index_in_array(array, value):
+    low = 0
+    high = len(array) - 1
+
+    while low <= high:
+        m = (low + high) // 2
+
+        if array[m] < value:
+            low = m + 1
+        elif array[m] > value:
+            high = m - 1
+        else:
+            return m
+
+    return None
+
+
 def array_insert_sorted(array, value):
     index = lower_bound(array, value)
     array.insert(index, value)
     return index
 
 
+# B+ Tree : START
+
+
+class Node:
+    def __init__(self, order):
+        self.order = order
+        self.is_leaf = True
+        self.keys = []
+        self.children = []
+
+
 def find_leaf(root, key):
     parents = []
     current = root
@@ -67,13 +85,7 @@ def node_is_full(node):
     return len(node.keys) == 2 * node.order
 
 
-def insert(root, key):
-    parents, leaf = find_leaf(root, key)
-
-    if node_is_full(leaf):
-        insert_full(root, parents, leaf, key, None)
-    else:
-        insert_non_full(leaf, key, None)
+# INSERTION : START
 
 
 def redistribute_keys(left_node, right_node, left_index, right_index):
@@ -145,7 +157,7 @@ def split_internal(node, key, right_child_node):
     return median_value, right_node
 
 
-def tree_grow(root, median_value, split_right_node):
+def bptree_grow(root, median_value, split_right_node):
     left_node = Node(root.order)
     left_node.is_leaf = split_right_node.is_leaf
     left_node.keys = root.keys
@@ -162,7 +174,7 @@ def insert_full(root, parents, node, key, previous_split_right_node):
         median_value, split_right_node = split_internal(node, key, previous_split_right_node)
 
     if node == root:
-        tree_grow(root, median_value, split_right_node)
+        bptree_grow(root, median_value, split_right_node)
     else:
         parent = parents.pop()
 
@@ -179,7 +191,59 @@ def insert_non_full(node, key, previous_split_right_node):
         node.children.insert(inserted_at_index + 1, previous_split_right_node)
 
 
-def tree_search(root, key):
+def bptree_insert(root, key):
+    parents, leaf = find_leaf(root, key)
+
+    if node_is_full(leaf):
+        insert_full(root, parents, leaf, key, None)
+    else:
+        insert_non_full(leaf, key, None)
+
+
+# INSERTION : END
+
+# DELETION : START
+
+
+def bptree_delete(root, key):
+    parents, leaf = find_leaf(root, key)
+
+    if not is_value_in_array(leaf.keys, key):
+        return
+
+    if len(leaf.keys) > leaf.order:
+        deletion_index = find_value_index_in_array(leaf.keys, key)
+        leaf.keys.pop(deletion_index)
+    else:
+        deletion_index = find_value_index_in_array(leaf.keys, key)
+        leaf.keys.pop(deletion_index)
+
+        parent = parents.pop()
+        children_index = None
+
+        for i, child in enumerate(parent.children):
+            if leaf == child:
+                children_index = i
+
+        if children_index == 0:
+            sibling = parent.children[children_index + 1]
+        else:
+            sibling = parent.children[children_index - 1]
+
+        if len(sibling.keys) == leaf.order:
+            pass
+        else:
+            # Works only if children_index = 0
+            borrowed_key = sibling.keys[0]
+            sibling.keys.pop(0)
+            leaf.keys.append(borrowed_key)
+            parent.keys[0] = sibling.keys[0]
+
+
+# DELETION : END
+
+
+def bptree_search(root, key):
     if root.is_leaf:
         return is_value_in_array(root.keys, key)
 
@@ -188,10 +252,10 @@ def tree_search(root, key):
     if children_index < len(root.keys) and root.keys[children_index] == key:
         children_index += 1
 
-    return tree_search(root.children[children_index], key)
+    return bptree_search(root.children[children_index], key)
 
 
-def tree_print(root, depth=0):
+def bptree_print(root, depth=0):
     print("  " * depth, end="")
     print(root.keys)
 
@@ -199,10 +263,10 @@ def tree_print(root, depth=0):
         return
 
     for child in root.children:
-        tree_print(child, depth + 1)
+        bptree_print(child, depth + 1)
 
 
-def extract_all_keys(root):
+def bptree_extract_all_keys(root):
     current = root
 
     while not current.is_leaf:
@@ -218,6 +282,9 @@ def extract_all_keys(root):
     return keys
 
 
+# B+ Tree : END
+
+
 def generate_random_keys(length, min_key, max_key):
     keys = []
 
@@ -236,28 +303,41 @@ def main():
     random.seed(0)
 
     order = 2
-    root = Node(order)
-    keys = generate_random_keys(40, 1, 99)
-    print(keys)
+    # root = Node(order)
+    # keys = generate_random_keys(40, 1, 99)
+    # print(keys)
 
-    for key in keys:
-        insert(root, key)
+    # for key in keys:
+    #     bptree_insert(root, key)
 
-    tree_print(root)
-    extracted_keys = extract_all_keys(root)
-    assert extracted_keys == sorted(keys)
+    # bptree_print(root)
+    # extracted_keys = bptree_extract_all_keys(root)
+    # assert extracted_keys == sorted(keys)
 
-    for key in keys:
-        assert tree_search(root, key)
+    # for key in keys:
+    #     assert bptree_search(root, key)
 
-    for _ in range(5):
-        while True:
-            random_key = random.randint(1, 99)
+    # for _ in range(5):
+    #     while True:
+    #         random_key = random.randint(1, 99)
 
-            if random_key not in keys:
-                break
+    #         if random_key not in keys:
+    #             break
+
+    #     assert not bptree_search(root, random_key)
+
+    root = Node(order)
+    keys = generate_random_keys(8, 1, 99)
+    print(keys)
+    print("=====")
+
+    for key in keys:
+        bptree_insert(root, key)
 
-        assert not tree_search(root, random_key)
+    bptree_delete(root, 51)
+    # bptree_delete(root, 52)
+    bptree_delete(root, 34)
+    bptree_print(root)
 
 
 if __name__ == "__main__":