diff --git a/ex3/ex3.c b/ex3/ex3.c
index 7113a3e7d40b0adfad8c585f14a2328982e0a8f5..aa630d2571b9beb07d53d1420b43c759e9885395 100644
--- a/ex3/ex3.c
+++ b/ex3/ex3.c
@@ -16,30 +16,343 @@
 #include <stdlib.h>
 #include <string.h>
 
+// LinkedListNode.h
+
+typedef struct LinkedListNode {
+    struct LinkedListNode *next;
+    char value;
+} LinkedListNode;
+
+LinkedListNode *linked_list_node_init(LinkedListNode *next, char value);
+void linked_list_node_destroy(LinkedListNode **node);
+
+// LinkedListNode.c
+
+LinkedListNode *linked_list_node_init(LinkedListNode *next, char value) {
+    LinkedListNode *node = (LinkedListNode *)malloc(sizeof(LinkedListNode));
+    node->next = next;
+    node->value = value;
+    return node;
+}
+
+void linked_list_node_destroy(LinkedListNode **node) {
+    free(*node);
+    *node = NULL;
+}
+
+// LinkedList.h
+
+typedef struct {
+    LinkedListNode *root;
+} LinkedList;
+
+LinkedList *linked_list_init();
+void linked_list_destroy(LinkedList **list);
+int32_t linked_list_count(LinkedList *list);
+bool linked_list_is_empty(LinkedList *list);
+LinkedListNode *linked_list_last(LinkedList *list);
+LinkedListNode *linked_list_add_last(LinkedList *list, char value);
+void linked_list_remove(LinkedList *list, LinkedListNode **node);
+void linked_list_print(LinkedList *list);
+
+// LinkedList.c
+
+LinkedList *linked_list_init() {
+    LinkedList *list = (LinkedList *)malloc(sizeof(LinkedList));
+    list->root = NULL;
+    return list;
+}
+
+void linked_list_destroy(LinkedList **list) {
+    LinkedListNode *current_node = (*list)->root;
+
+    while (current_node != NULL) {
+        LinkedListNode *current_node_copy = current_node;
+        current_node = current_node->next;
+        free(current_node_copy);
+    }
+
+    free(*list);
+    *list = NULL;
+}
+
+int32_t linked_list_count(LinkedList *list) {
+    LinkedListNode *current_node = list->root;
+    int32_t count = 0;
+
+    while (current_node != NULL) {
+        count += 1;
+        current_node = current_node->next;
+    }
+
+    return count;
+}
+
+bool linked_list_is_empty(LinkedList *list) {
+    return linked_list_count(list) == 0;
+}
+
+LinkedListNode *linked_list_last(LinkedList *list) {
+    LinkedListNode *current_node = list->root;
+
+    while (current_node->next != NULL) {
+        current_node = current_node->next;
+    }
+
+    return current_node;
+}
+
+LinkedListNode *linked_list_add_last(LinkedList *list, char value) {
+    LinkedListNode *new_node = linked_list_node_init(NULL, value);
+
+    if (linked_list_is_empty(list)) {
+        list->root = new_node;
+    } else {
+        LinkedListNode *current_node = list->root;
+
+        while (current_node->next != NULL) {
+            current_node = current_node->next;
+        }
+
+        current_node->next = new_node;
+    }
+
+    return new_node;
+}
+
+void linked_list_remove(LinkedList *list, LinkedListNode **node) {
+    if (list->root == (*node)) {
+        list->root = (*node)->next;
+    } else {
+        LinkedListNode *current_node = list->root;
+
+        while (current_node->next != (*node)) {
+            current_node = current_node->next;
+        }
+
+        current_node->next = current_node->next->next;
+    }
+
+    free(*node);
+    *node = NULL;
+}
+
+void linked_list_print(LinkedList *list) {
+    LinkedListNode *current_node = list->root;
+
+    while (current_node != NULL) {
+        printf("%c ", current_node->value);
+        current_node = current_node->next;
+    }
+}
+
+// Stack.h
+
+typedef struct Stack {
+    LinkedList *list;
+} Stack;
+
+Stack *stack_init();
+void stack_destroy(Stack **stack);
+void stack_push(Stack *stack, char value);
+char stack_peek(Stack *stack);
+char stack_pop(Stack *stack);
+
+// Stack.c
+
+Stack *stack_init() {
+    Stack *stack = (Stack *)malloc(sizeof(Stack));
+    stack->list = linked_list_init();
+    return stack;
+}
+
+void stack_destroy(Stack **stack) {
+    linked_list_destroy(&(*stack)->list);
+    free(*stack);
+    *stack = NULL;
+}
+
+void stack_push(Stack *stack, char value) {
+    linked_list_add_last(stack->list, value);
+}
+
+char stack_peek(Stack *stack) {
+    return linked_list_last(stack->list)->value;
+}
+
+char stack_pop(Stack *stack) {
+    char value = stack_peek(stack);
+
+    LinkedListNode *last_node = linked_list_last(stack->list);
+    linked_list_remove(stack->list, &last_node);
+
+    return value;
+}
+
+void stack_print(Stack *stack) {
+    while (!linked_list_is_empty(stack->list)) {
+        printf("%c ", stack_pop(stack));
+    }
+    printf("\n");
+}
+
+// BinarySearchTree.h
+
+typedef struct Node {
+    struct Node *left;
+    struct Node *right;
+    int32_t key;
+} Node;
+
+Node *node_init();
+void node_destroy(Node **node);
+
+Node *binary_search_tree_init();
+void binary_search_tree_destroy(Node **root);
+Node *binary_search_tree_insert(Node *root, int32_t key);
+Node *binary_search_tree_search(Node *root, int32_t key);
+Node *binary_search_tree_find_smallest_node(Node *root);
+Node *binary_search_tree_delete(Node *root, int32_t key);
+void binary_search_tree_print(Node *root, int32_t depth);
+
+// BinarySearchTree.c
+
+Node *node_init(int32_t key) {
+    Node *node = (Node *)malloc(sizeof(Node));
+    node->left = NULL;
+    node->right = NULL;
+    node->key = key;
+    return node;
+}
+
+void node_destroy(Node **node) {
+    free(*node);
+    *node = NULL;
+}
+
+Node *binary_search_tree_init() {
+    return NULL;
+}
+
+void binary_search_tree_destroy(Node **root) {
+    if (*root != NULL) {
+        binary_search_tree_destroy(&(*root)->left);
+        binary_search_tree_destroy(&(*root)->right);
+        free(*root);
+        *root = NULL;
+    }
+}
+
+Node *binary_search_tree_insert(Node *root, int32_t key) {
+    if (root == NULL) {
+        return node_init(key);
+    }
+
+    if (key < root->key) {
+        root->left = binary_search_tree_insert(root->left, key);
+    } else if (key > root->key) {
+        root->right = binary_search_tree_insert(root->right, key);
+    }
+
+    return root;
+}
+
+Node *binary_search_tree_search(Node *root, int32_t key) {
+    if (root == NULL) {
+        return NULL;
+    }
+
+    if (key < root->key) {
+        return binary_search_tree_search(root->left, key);
+    } else if (key > root->key) {
+        return binary_search_tree_search(root->right, key);
+    }
+
+    return root;
+}
+
+Node *binary_search_tree_find_smallest_node(Node *root) {
+    while (root->left != NULL) {
+        root = root->left;
+    }
+
+    return root;
+}
+
+Node *binary_search_tree_delete(Node *root, int32_t key) {
+    if (root == NULL) {
+        return NULL;
+    }
+
+    if (key < root->key) {
+        root->left = binary_search_tree_delete(root->left, key);
+    } else if (key > root->key) {
+        root->right = binary_search_tree_delete(root->right, key);
+    } else {
+        if (root->left == NULL && root->right == NULL) {
+            node_destroy(&root);
+            return NULL;
+        }
+
+        if (root->left == NULL) {
+            Node *right = root->right;
+            node_destroy(&root);
+            return right;
+        }
+
+        if (root->right == NULL) {
+            Node *left = root->left;
+            node_destroy(&root);
+            return left;
+        }
+
+        Node *smallest = binary_search_tree_find_smallest_node(root->right);
+        root->key = smallest->key;
+        root->right = binary_search_tree_delete(root->right, smallest->key);
+    }
+
+    return root;
+}
+
+// ---
+
+bool node_is_leaf(Node *node) {
+    return node->left == NULL && node->right == NULL;
+}
+
+Stack *search_path(Node *root, int key) {
+    Stack *s = stack_init();
+
+    while (root != NULL && !node_is_leaf(root) && root->key != key) {
+        if (key < root->key) {
+            root = root->left;
+            stack_push(s, 'g');
+        } else if (key > root->key) {
+            root = root->right;
+            stack_push(s, 'd');
+        }
+    }
+
+    return s;
+}
+
 int main() {
-    // int32_t values_length = 5;
-    // double values[values_length];
-
-    // for (int32_t i = 0; i < values_length; i += 1) {
-    //     double value;
-    //     scanf("%lf", &value);
-    //     values[i] = value;
-    // }
-
-    // int32_t values_length = 5;
-    // int32_t values[values_length];
-
-    // for (int32_t i = 0; i < values_length; i += 1) {
-    //     int32_t value;
-    //     scanf("%d", &value);
-    //     values[i] = value;
-    // }
-
-    // char a[100];
-    // int32_t b;
-    // scanf("%s %d", a, &b);
-    // printf("%s %d\n", a, b);
-
-    printf("ex1\n");
+    Node *root = binary_search_tree_init();
+    int numbers_length = 9;
+    int numbers[] = {10, 0, 20, -5, 5, 15, 25, 22, 24};
+
+    for (int i = 0; i < numbers_length; i += 1) {
+        root = binary_search_tree_insert(root, numbers[i]);
+    }
+
+    Stack *s = search_path(root, 24);
+    stack_print(s);
+    stack_destroy(&s);
+
+    s = search_path(root, 7);
+    stack_print(s);
+    stack_destroy(&s);
+
+    binary_search_tree_destroy(&root);
     return EXIT_SUCCESS;
 }