diff --git a/__main__.py b/__main__.py
index 66507d0ed76dbc31b5dc975b8649fcc3a647490b..e4d7be275907b2f0e7122281df9a5a7c0d32a966 100644
--- a/__main__.py
+++ b/__main__.py
@@ -224,6 +224,10 @@ def bptree_find_smallest_key(root):
     return bptree_find_smallest_key(root.children[0])
 
 
+def is_sibling_left_side(parent, node, sibling):
+    return find_child_index(parent, sibling) < find_child_index(parent, node)
+
+
 def bptree_shrink(root):
     child = root.children[0]
     root.keys = child.keys.copy()
@@ -231,26 +235,37 @@ def bptree_shrink(root):
     root.is_leaf = child.is_leaf
 
 
-def bptree_steal_internal():
-    # TODO
-    pass
+def bptree_steal_internal(parent, node, child_index, sibling):
+    if is_sibling_left_side(parent, node, sibling):
+        node.keys.insert(0, parent.keys[child_index - 1])
+        parent.keys[child_index - 1] = sibling.keys[len(sibling.keys) - 1]
+        sibling.keys.pop(len(sibling.keys) - 1)
+        node.children.insert(0, sibling.children[len(sibling.children) - 1])
+        sibling.children.pop(len(sibling.children) - 1)
+    else:
+        node.keys.append(parent.keys[child_index])
+        parent.keys[child_index] = sibling.keys[0]
+        sibling.keys.pop(0)
+        node.children.append(sibling.children[0])
+        sibling.children.pop(0)
 
 
-def bptree_steal_leaf(parent, node, child_index, sibling, sibling_side):
-    if sibling_side == "l":
-        sibling_key = sibling.keys[len(sibling.keys) - 1]
-        sorted_array_delete(sibling.keys, sibling_key)
-        sorted_array_insert(node.keys, sibling_key)
-        parent.keys[child_index - 1] = sibling_key
-    elif sibling_side == "r":
-        sibling_key = sibling.keys[0]
-        sorted_array_delete(sibling.keys, sibling_key)
-        sorted_array_insert(node.keys, sibling_key)
+def bptree_steal_leaf(parent, node, child_index, sibling):
+    if is_sibling_left_side(parent, node, sibling):
+        stealed_key = sibling.keys[len(sibling.keys) - 1]
+        sibling.keys.pop(len(sibling.keys) - 1)
+        parent.keys[child_index - 1] = stealed_key
+        node.keys.insert(0, stealed_key)
+    else:
+        stealed_key = sibling.keys[0]
+        sibling.keys.pop(0)
         parent.keys[child_index] = sibling.keys[0]
+        node.keys.append(stealed_key)
 
 
 def _bptree_merge(parent, main_node, secondary_node, pivot_index):
     if not main_node.is_leaf:
+        print(pivot_index)
         parent_key = parent.keys[pivot_index]
         main_node.keys.insert(0, parent_key)
 
@@ -265,11 +280,13 @@ def _bptree_merge(parent, main_node, secondary_node, pivot_index):
     parent.children.pop(pivot_index)
 
 
-def bptree_merge(parent, node, child_index, sibling, sibling_side):
-    if sibling_side == "l":
+def bptree_merge(parent, node, sibling):
+    child_index = find_child_index(parent, node)
+
+    if is_sibling_left_side(parent, node, sibling):
         # The sibling is merged into the node.
         _bptree_merge(parent, node, sibling, child_index - 1)
-    elif sibling_side == "r":
+    else:
         # The node is merged into the sibling.
         _bptree_merge(parent, sibling, node, child_index)
 
@@ -282,31 +299,24 @@ def find_child_index(parent, child):
     return None
 
 
-def bptree_find_sibling(parent, child_index):
+def bptree_find_sibling(parent, node):
+    child_index = find_child_index(parent, node)
+
     if child_index == 0:
         # Must take the sibling on the right.
-        sibling = parent.children[1]
-        sibling_position = "r"
-    elif child_index == len(parent.children) - 1:
+        return parent.children[1]
+    if child_index == len(parent.children) - 1:
         # Must take the sibling on the left.
-        sibling = parent.children[len(parent.children) - 2]
-        sibling_position = "l"
-    else:
+        return parent.children[len(parent.children) - 2]
         # Can take the sibling from left or right.
-        if len(parent.children[child_index - 1].keys) > parent.order:
-            # The left sibling has enough keys to borrow one.
-            sibling = parent.children[child_index - 1]
-            sibling_position = "l"
-        elif len(parent.children[child_index + 1].keys) > parent.order:
-            # The right sibling has enough keys to borrow one.
-            sibling = parent.children[child_index + 1]
-            sibling_position = "r"
-        else:
-            # A merge between the node and the left sibling is required.
-            sibling = parent.children[child_index - 1]
-            sibling_position = "l"
-
-    return sibling, sibling_position
+    if len(parent.children[child_index - 1].keys) > parent.order:
+        # The left sibling has enough keys to borrow one.
+        return parent.children[child_index - 1]
+    if len(parent.children[child_index + 1].keys) > parent.order:
+        # The right sibling has enough keys to borrow one.
+        return parent.children[child_index + 1]
+    # A merge between the node and the left sibling is required.
+    return parent.children[child_index - 1]
 
 
 def _bptree_delete(root, parents, node, key):
@@ -316,40 +326,27 @@ def _bptree_delete(root, parents, node, key):
         parent = parents.pop()
 
     if node.is_leaf:
-        keys_length = len(node.keys)
         sorted_array_delete(node.keys, key)
 
-        if keys_length == node.order and node != root:
-            child_index = find_child_index(parent, node)
-            sibling, sibling_side = bptree_find_sibling(parent, child_index)
-
-            if len(sibling.keys) == sibling.order:
-                # There is not enough key in the left and right siblings.
-                bptree_merge(parent, node, child_index, sibling, sibling_side)
-
-                if parent == root and len(parent.keys) == 0:
-                    bptree_shrink(root)
-                    parent = None
-            else:
-                # There are enough keys in the sibling to steal one.
-                bptree_steal_leaf(parent, node, child_index, sibling, sibling_side)
-    else:
-        if node != root and len(node.keys) < node.order:
-            child_index = find_child_index(parent, node)
-            sibling, sibling_side = bptree_find_sibling(parent, child_index)
+    if node != root and len(node.keys) < node.order:
+        child_index = find_child_index(parent, node)
+        sibling = bptree_find_sibling(parent, node)
 
-            if len(sibling.keys) == sibling.order:
-                bptree_merge(parent, node, child_index, sibling, sibling_side)
+        if len(sibling.keys) == sibling.order:
+            bptree_merge(parent, node, sibling)
 
-                if parent == root and len(parent.keys) == 0:
-                    bptree_shrink(root)
-                    parent = None
+            if parent == root and len(parent.keys) == 0:
+                bptree_shrink(root)
+                parent = None
+        else:
+            if node.is_leaf:
+                bptree_steal_leaf(parent, node, child_index, sibling)
             else:
-                print("???????????")
+                bptree_steal_internal(parent, node, child_index, sibling)
 
-        if len(node.children) > 0 and is_value_in_array(node.keys, key):
-            index = find_value_index_in_array(node.keys, key)
-            node.keys[index] = bptree_find_smallest_key(node.children[index + 1])
+    if not node.is_leaf and len(node.children) > 0 and is_value_in_array(node.keys, key):
+        index = find_value_index_in_array(node.keys, key)
+        node.keys[index] = bptree_find_smallest_key(node.children[index + 1])
 
     if parent is not None:
         _bptree_delete(root, parents, parent, key)
@@ -442,16 +439,17 @@ def generate_random_keys(length, min_key, max_key):
 def main():
     a = 2
     random.seed(a)
-
     order = 2
-    root = Node(order)
-    keys = generate_random_keys(40, 1, 99)
-    print(keys)
+    # =====================================================================
 
-    for key in keys:
-        bptree_insert(root, key)
+    # root = Node(order)
+    # keys = generate_random_keys(40, 1, 99)
+    # print(keys)
 
-    bptree_print(root)
+    # for key in keys:
+    #     bptree_insert(root, key)
+
+    # bptree_print(root)
     # extracted_keys = bptree_extract_all_keys(root)
     # assert extracted_keys == sorted(keys)
 
@@ -467,20 +465,27 @@ def main():
 
     #     assert not bptree_search(root, random_key)
 
-    # root = Node(order)
-    # keys = generate_random_keys(30, 1, 99)
-    # print(keys)
-    # print("=====")
+    # =====================================================================
 
-    # for key in keys:
-    #     bptree_insert(root, key)
+    root = Node(order)
+    keys = generate_random_keys(30, 1, 99)
+    print(keys)
+    print("=====")
 
-    # bptree_delete(root, 65)
-    # bptree_delete(root, 57)
-    # bptree_delete(root, 47)
-    # # bptree_delete(root, 65)
+    for key in keys:
+        bptree_insert(root, key)
 
-    # bptree_print(root)
+    bptree_delete(root, 65)
+    bptree_delete(root, 57)
+    bptree_delete(root, 47)
+    bptree_delete(root, 28)
+    bptree_delete(root, 51)
+    bptree_insert(root, 100)
+    bptree_delete(root, 48)
+    bptree_delete(root, 41)
+    bptree_delete(root, 60)
+
+    bptree_print(root)
 
 
 if __name__ == "__main__":
diff --git a/src/Array.c b/src/Array.c
index e9d75d65b206a61a886d7053dc694acec2d885b8..c6a437e543813f7c5599e79ec4f745bbc9f962c8 100644
--- a/src/Array.c
+++ b/src/Array.c
@@ -87,6 +87,14 @@ bool IntegerArray_binary_search(IntegerArray *array, uint64_t item, int *index)
     return *index != -1;
 }
 
+void IntegerArray_delete_at_index(IntegerArray *array, int index) {
+    for (int i = index; i < array->size; i++) {
+        array->items[i] = array->items[i + 1];
+    }
+
+    array->size--;
+}
+
 void IntegerArray_print(IntegerArray *array) {
     printf("[");
 
diff --git a/src/Array.h b/src/Array.h
index e48817e428719ca779c474cea4e4b85818f086c6..99f19602017854ee6fc9affabb16e15985470d5e 100644
--- a/src/Array.h
+++ b/src/Array.h
@@ -21,6 +21,7 @@ void IntegerArray_insert_at_index(IntegerArray *array, int index, uint64_t item)
 void IntegerArray_append(IntegerArray *array, uint64_t item);
 bool IntegerArray_binary_search(IntegerArray *array, uint64_t item, int *index);
 void IntegerArray_delete_sorted(IntegerArray *array, uint64_t item);
+void IntegerArray_delete_at_index(IntegerArray *array, int index);
 void IntegerArray_print(IntegerArray *array);
 void IntegerArray_clear(IntegerArray *array);
 void IntegerArray_copy(IntegerArray *src, IntegerArray *dest);
diff --git a/src/BPTree.c b/src/BPTree.c
index 50a78b538bafb3de6230762e88961769acc8eae7..de6852a35e1423d5cbeee3cc3675f732ba0f4de9 100644
--- a/src/BPTree.c
+++ b/src/BPTree.c
@@ -259,3 +259,138 @@ void BPTree_insert(BPTreeNode *root, uint64_t key, uint64_t data) {
 }
 
 // Deletion
+
+static uint64_t find_smallest_key(BPTreeNode *root);
+static int find_child_index(BPTreeNode *parent, BPTreeNode *child);
+static bool is_sibling_left_side(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling);
+static void shrink(BPTreeNode *root);
+static void steal_internal(BPTreeNode *parent, BPTreeNode *node, int child_index, BPTreeNode *sibling);
+static void steal_leaf(BPTreeNode *parent, BPTreeNode *node, int child_index, BPTreeNode *sibling);
+static void _bptree_merge(BPTreeNode *parent, BPTreeNode *main_node, BPTreeNode *secondary_node, int pivot_index);
+static void bptree_merge(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling);
+static BPTreeNode *find_sibling(BPTreeNode *parent, BPTreeNode *node);
+
+    static uint64_t find_smallest_key(BPTreeNode *root) {
+    if (root->is_leaf) {
+        return root->keys->items[0];
+    }
+
+    return find_smallest_key(root->children->items[0]);
+}
+
+static int find_child_index(BPTreeNode *parent, BPTreeNode *child) {
+    for (int i = 0; i < parent->children->size; i++) {
+        if (child == parent->children->items[i]) {
+            return i;
+        }
+    }
+
+    return -1;
+}
+
+static bool is_sibling_left_side(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling) {
+    return find_child_index(parent, sibling) < find_child_index(parent, node);
+}
+
+static void shrink(BPTreeNode *root) {
+    BPTreeNode *child = root->children->items[0];
+    root->is_leaf = child->is_leaf;
+
+    // No keys, it's obvious
+    // IntegerArray_clear(root->keys);
+    IntegerArray_copy(child->keys, root->keys);
+
+    BPTreeNodeArray_clear(root->children);
+    BPTreeNodeArray_copy(child->children, root->children);
+
+    BPTreeNodeArray_clear(child->children);
+    BPTree_destroy(&child);
+}
+
+static void steal_internal(BPTreeNode *parent, BPTreeNode *node, int child_index, BPTreeNode *sibling) {
+    if (is_sibling_left_side(parent, node, sibling)) {
+        IntegerArray_insert_at_index(node->keys, 0, parent->keys->items[child_index - 1]);
+        parent->keys->items[child_index - 1] = sibling->keys->items[sibling->keys->size - 1];
+        IntegerArray_delete_at_index(sibling->keys, sibling->keys->size - 1);
+        BPTreeNodeArray_insert_at_index(node->children, 0, sibling->children->items[sibling->children->size - 1]);
+        BPTreeNodeArray_delete_at_index(sibling->children, sibling->children->size - 1);
+    } else {
+        IntegerArray_append(node->keys, parent->keys->items[child_index]);
+        parent->keys->items[child_index] = sibling->keys->items[0];
+        IntegerArray_delete_at_index(sibling->keys, 0);
+        BPTreeNodeArray_append(node->children, sibling->children->items[0]);
+        BPTreeNodeArray_delete_at_index(sibling->children, 0);
+    }
+}
+
+static void steal_leaf(BPTreeNode *parent, BPTreeNode *node, int child_index, BPTreeNode *sibling) {
+    if (is_sibling_left_side(parent, node, sibling)) {
+        uint64_t stealed_key = sibling->keys->items[sibling->keys->size - 1];
+        IntegerArray_delete_at_index(sibling->keys, sibling->keys->size - 1);
+        parent->keys->items[child_index - 1] = stealed_key;
+        IntegerArray_insert_at_index(node->keys, 0, stealed_key);
+    } else {
+        uint64_t stealed_key = sibling->keys->items[0];
+        IntegerArray_delete_at_index(sibling->keys, 0);
+        parent->keys->items[child_index] = sibling->keys->items[0];
+        IntegerArray_append(node->keys, stealed_key);
+    }
+}
+
+static void _bptree_merge(BPTreeNode *parent, BPTreeNode *main_node, BPTreeNode *secondary_node, int pivot_index) {
+    if (!main_node->is_leaf) {
+        IntegerArray_insert_at_index(main_node->keys, 0, parent->keys->items[pivot_index]);
+    }
+
+    for (int i = secondary_node->keys->size - 1; i >= 0; i--) {
+        IntegerArray_insert_at_index(main_node->keys, 0, secondary_node->keys->items[i]);
+    }
+
+    if (!main_node->is_leaf) {
+        for (int i = secondary_node->children->size - 1; i >= 0; i--) {
+            BPTreeNodeArray_insert_at_index(main_node->children, 0, secondary_node->children->items[i]);
+        }
+    }
+
+    IntegerArray_delete_at_index(parent->keys, pivot_index);
+    BPTreeNodeArray_delete_at_index(parent->children, pivot_index);
+}
+
+static void bptree_merge(BPTreeNode *parent, BPTreeNode *node, BPTreeNode *sibling) {
+    int child_index = find_child_index(parent, node);
+
+    if (is_sibling_left_side(parent, node, sibling)) {
+        _bptree_merge(parent, node, sibling, child_index - 1);
+    } else {
+        _bptree_merge(parent, sibling, node, child_index);
+    }
+}
+
+static BPTreeNode *find_sibling(BPTreeNode *parent, BPTreeNode *node) {
+    int child_index = find_child_index(parent, node);
+
+    if (child_index == 0) {
+        return parent->children->items[1];
+    }
+
+    if (child_index == parent->children->size - 1) {
+        return parent->children->items[parent->children->size - 2];
+    }
+
+    if (parent->children->items[child_index - 1]->keys->size > parent->order) {
+        return parent->children->items[child_index - 1];
+    }
+
+    if (parent->children->items[child_index + 1]->keys->size > parent->order) {
+        return parent->children->items[child_index + 1];
+    }
+
+    return parent->children->items[child_index - 1];
+}
+
+static void _bptree_delete(BPTreeNode *root, BPTreeNodeArray *parents, BPTreeNode *node, uint64_t key) {
+    BPTreeNode *parent = NULL;
+}
+
+void BPTree_delete(BPTreeNode *root, uint64_t key) {
+}
diff --git a/src/BPTree.h b/src/BPTree.h
index 41962bf7fba8e3fb22e561e5ed0bd38ed85934b1..2c83b499629a5f195895f6ac10927aa5b17c77f0 100644
--- a/src/BPTree.h
+++ b/src/BPTree.h
@@ -27,4 +27,6 @@ void BPTree_insert(BPTreeNode *root, uint64_t key, uint64_t data);
 
 // Deletion
 
+void BPTree_delete(BPTreeNode *root, uint64_t key);
+
 #endif