diff --git a/01-tree_successor/cpp/Makefile b/01-tree_successor/cpp/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..9feafbe75fdce9e90992dd6e409d359fea098b3c
--- /dev/null
+++ b/01-tree_successor/cpp/Makefile
@@ -0,0 +1,12 @@
+test: tree_successor_test
+	./$<
+
+CXXFLAGS=-std=c++11 -O2 -Wall -Wextra -g -Wno-sign-compare
+
+tree_successor_test: tree_successor.h tree_successor_test.cpp test_main.cpp
+	$(CXX) $(CXXFLAGS) $^ -o $@
+
+clean:
+	rm -f tree_successor_test
+
+.PHONY: clean test
diff --git a/01-tree_successor/cpp/test_main.cpp b/01-tree_successor/cpp/test_main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3f4aff0785f636b7fd0ea1a15aa69dafe06f290f
--- /dev/null
+++ b/01-tree_successor/cpp/test_main.cpp
@@ -0,0 +1,43 @@
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <string>
+#include <utility>
+#include <vector>
+
+using namespace std;
+
+extern vector<pair<string, function<void()>>> tests;
+
+void expect_failed(const string& message) {
+    cerr << "Test error: " << message << endl;
+    exit(1);
+}
+
+int main(int argc, char* argv[]) {
+    vector<string> required_tests;
+
+    if (argc > 1) {
+        required_tests.assign(argv + 1, argv + argc);
+    } else {
+        for (const auto& test : tests)
+            required_tests.push_back(test.first);
+    }
+
+    for (const auto& required_test : required_tests) {
+        bool found = false;
+        for (const auto& test : tests)
+            if (required_test == test.first) {
+                cerr << "Running test " << required_test << endl;
+                test.second();
+                found = true;
+                break;
+            }
+        if (!found) {
+            cerr << "Unknown test " << required_test << endl;
+            return 1;
+        }
+    }
+
+    return 0;
+}
diff --git a/01-tree_successor/cpp/tree_successor.h b/01-tree_successor/cpp/tree_successor.h
new file mode 100644
index 0000000000000000000000000000000000000000..d1306f6ea2e0fa3af6674da904e72898fe1dcc45
--- /dev/null
+++ b/01-tree_successor/cpp/tree_successor.h
@@ -0,0 +1,73 @@
+// A node of the tree
+class Node {
+  public:
+    int key;
+    Node* left;
+    Node* right;
+    Node* parent;
+
+    // Constructor
+    Node(int key, Node* parent=nullptr) {
+        this->key = key;
+        this->parent = parent;
+        this->left = nullptr;
+        this->right = nullptr;
+    }
+};
+
+// Binary tree
+class Tree {
+  public:
+    // Pointer to root of the tree; nullptr if the tree is empty.
+    Node* root = nullptr;
+
+    // Insert a key into the tree.
+    // If the key is already present, nothing happens.
+    void insert(int key) {
+        if (!root) {
+            root = new Node(key);
+            return;
+        }
+
+        Node* node = root;
+        while (node->key != key) {
+            if (key < node->key) {
+                if (!node->left)
+                    node->left = new Node(key, node);
+                node = node->left;
+            } else {
+                if (!node->right)
+                    node->right = new Node(key, node);
+                node = node->right;
+            }
+        }
+    }
+
+    // Return successor of the given node.
+    //
+    // The successor of a node is the node with the next higher key.
+    // Return nullptr if there is no such node.
+    // If the argument is nullptr, return the node with the smallest key.
+    Node* successor(Node* node) {
+        // TODO: Implement
+    }
+
+    // Destructor to free all allocated memory.
+    ~Tree() {
+        Node* node = root;
+        while (node) {
+            Node* next;
+            if (node->left) {
+                next = node->left;
+                node->left = nullptr;
+            } else if (node->right) {
+                next = node->right;
+                node->right = nullptr;
+            } else {
+                next = node->parent;
+                delete node;
+            }
+            node = next;
+        }
+    }
+};
diff --git a/01-tree_successor/cpp/tree_successor_test.cpp b/01-tree_successor/cpp/tree_successor_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8b794af982614769d379d77b4f896f5803bdffec
--- /dev/null
+++ b/01-tree_successor/cpp/tree_successor_test.cpp
@@ -0,0 +1,54 @@
+#include <algorithm>
+#include <functional>
+#include <cstdint>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "tree_successor.h"
+
+using namespace std;
+
+// If the condition is not true, report an error and halt.
+#define EXPECT(condition, message) do { if (!(condition)) expect_failed(message); } while (0)
+void expect_failed(const string& message);
+
+void test(const vector<int>& sequence) {
+    Tree tree;
+    for (const auto& element : sequence)
+        tree.insert(element);
+
+    vector<int> sorted_sequence(sequence);
+    sort(sorted_sequence.begin(), sorted_sequence.end());
+
+    Node* node = tree.successor(nullptr);
+    for (const auto& element : sorted_sequence) {
+        EXPECT(node, "Expected successor " + to_string(element) + ", got nullptr");
+        EXPECT(node->key == element,
+               "Expected successor " + to_string(element) + ", got " + to_string(node->key));
+        node = tree.successor(node);
+    }
+    EXPECT(!node, "Expected no successor, got " + to_string(node->key));
+}
+
+vector<pair<string, function<void()>>> tests = {
+    {"right_path", []
+        { vector<int> numbers;
+            for (int i = 0; i < 10000; i++) numbers.push_back((int)(7.13*i));
+            test(numbers);
+        }
+    },
+    {"left_path", []
+        { vector<int> numbers;
+            for (int i = 9999; i >= 0; i--) numbers.push_back((int)(7.13*i));
+            test(numbers);
+        }
+    },
+    {"random_tree", []
+        { vector<int> numbers = {997};
+            for (int i = 2; i < 199999; i++)
+                numbers.push_back((numbers.back() * int64_t(997)) % 199999);
+            test(numbers);
+        }
+    },
+};
diff --git a/01-tree_successor/python/tree_successor.py b/01-tree_successor/python/tree_successor.py
new file mode 100644
index 0000000000000000000000000000000000000000..d0377ab6cf0725f68a0f4542a97b78aadc1fcfa7
--- /dev/null
+++ b/01-tree_successor/python/tree_successor.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+
+class Node:
+    """Node in a binary tree `Tree`"""
+
+    def __init__(self, key, left=None, right=None, parent=None):
+        self.key = key
+        self.left = left
+        self.right = right
+        self.parent = parent
+
+class Tree:
+    """A simple binary search tree"""
+
+    def __init__(self, root=None):
+        self.root = root
+
+    def insert(self, key):
+        """Insert key into the tree.
+
+        If the key is already present, do nothing.
+        """
+        if self.root is None:
+            self.root = Node(key)
+            return
+
+        node = self.root
+        while node.key != key:
+            if key < node.key:
+                if node.left is None:
+                    node.left = Node(key, parent=node)
+                node = node.left
+            else:
+                if node.right is None:
+                    node.right = Node(key, parent=node)
+                node = node.right
+
+    def successor(self, node=None):
+        """Return successor of the given node.
+
+        The successor of a node is the node with the next greater key.
+        Return None if there is no such node.
+        If the argument is None, return the node with the smallest key.
+        """
+        # TODO: Implement
+        raise NotImplementedError
diff --git a/01-tree_successor/python/tree_successor_test.py b/01-tree_successor/python/tree_successor_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..41d691423275ead31f514068f9e27913f195c871
--- /dev/null
+++ b/01-tree_successor/python/tree_successor_test.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+import sys
+
+import tree_successor
+
+def test_sequence(sequence):
+    tree = tree_successor.Tree()
+    for i in sequence: tree.insert(i)
+
+    node = tree.successor(None)
+    for element in sorted(sequence):
+        assert node is not None, "Expected successor {}, got None".format(element)
+        assert node.key == element, "Expected successor {}, got {}".format(element, node.key)
+        node = tree.successor(node)
+    assert node is None, "Expected no successor, got {}".format(node.key)
+
+def gen_increasing_seq():
+    return [int(7.13*i) for i in range(10000)]
+
+tests = [
+    ("right_path", lambda: test_sequence(gen_increasing_seq())),
+    ("left_path", lambda: test_sequence(list(reversed(gen_increasing_seq())))),
+    ("random_tree", lambda: test_sequence([pow(997, i, 199999) for i in range(1, 199999)])),
+]
+
+if __name__ == "__main__":
+    for required_test in sys.argv[1:] or [name for name, _ in tests]:
+        for name, test in tests:
+            if name == required_test:
+                print("Running test {}".format(name), file=sys.stderr)
+                test()
+                break
+        else:
+            raise ValueError("Unknown test {}".format(name))
diff --git a/01-tree_successor/task.md b/01-tree_successor/task.md
new file mode 100644
index 0000000000000000000000000000000000000000..eb2187e4730cf2624feb5b43db16c564dcb97fed
--- /dev/null
+++ b/01-tree_successor/task.md
@@ -0,0 +1,13 @@
+Given an implementation of a simple binary search tree including parent
+pointers, implement a `successor` method. The methods is given a node
+and it should return another node of the tree with the next higher key
+(i.e., the smallest of keys which are greater than the given one).
+
+- If there is no such node, it should return a null pointer.
+- The given node can also be a null pointer, in which case the method should
+  return the smallest node in the tree.
+
+You can expect that `successor` method is never called on an empty tree.
+
+You should submit the file `tree_successor.*` (but not the
+`tree_successor_test.*`).