Commit 8d72de3c authored by Ondřej Mička's avatar Ondřej Mička

Removed past assignments

parent 3ec36a4b
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
#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;
}
// 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;
}
}
};
#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 = {
{"path", []
{ vector<int> numbers;
for (int i = 0; i < 10000; i++) numbers.push_back(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);
}
},
};
#!/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
#!/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)
tests = [
("path", lambda: test_sequence(range(3000))),
("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))
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 should submit the file `tree_successor.*` (but not the
`tree_successor_test.*`).
test: splay_operation_test
./$<
CXXFLAGS=-std=c++11 -O2 -Wall -Wextra -g -Wno-sign-compare
splay_operation_test: splay_operation.h splay_operation_test.cpp test_main.cpp
$(CXX) $(CXXFLAGS) $^ -o $@
clean::
rm -f splay_operation_test
.PHONY: clean test
// A node of the tree
class Node {
public:
int key;
Node* left;
Node* right;
Node* parent;
// Constructor
Node(int key, Node* parent=nullptr, Node* left=nullptr, Node* right=nullptr) {
this->key = key;
this->parent = parent;
this->left = left;
this->right = right;
if (left) left->parent = this;
if (right) right->parent = this;
}
};
// Binary tree
class Tree {
public:
// Pointer to root of the tree; nullptr if the tree is empty.
Node* root;
Tree(Node* root=nullptr) {
this->root = root;
}
// Rotate the given `node` up. Perform a single rotation of the edge
// between the node and its parent, choosing left or right rotation
// appropriately.
virtual void rotate(Node* node) {
if (node->parent) {
if (node->parent->left == node) {
if (node->right) node->right->parent = node->parent;
node->parent->left = node->right;
node->right = node->parent;
} else {
if (node->left) node->left->parent = node->parent;
node->parent->right = node->left;
node->left = node->parent;
}
if (node->parent->parent) {
if (node->parent->parent->left == node->parent)
node->parent->parent->left = node;
else
node->parent->parent->right = node;
} else {
root = node;
}
Node* original_parent = node->parent;
node->parent = node->parent->parent;
original_parent->parent = node;
}
}
// Look up the given key in the tree, returning the
// the node with the requested key or nullptr.
Node* lookup(int key) {
// TODO: Utilize splay suitably.
Node* node = root;
while (node) {
if (node->key == key) {
return node;
}
if (key < node->key)
node = node->left;
else
node = node->right;
}
return nullptr;
}
// Insert a key into the tree.
// If the key is already present, nothing happens.
void insert(int key) {
// TODO: Utilize splay suitably.
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;
}
}
}
// Delete given key from the tree.
// It the key is not present, do nothing.
void remove(int key) {
// TODO: Utilize splay suitably.
Node* node = root;
while (node && node->key != key) {
if (key < node->key)
node = node->left;
else
node = node->right;
}
if (node) {
if (node->left && node->right) {
Node* replacement = node->right;
while (replacement->left)
replacement = replacement->left;
node->key = replacement->key;
node = replacement;
}
Node* replacement = node->left ? node->left : node->right;
if (node->parent) {
if (node->parent->left == node) node->parent->left = replacement;
else node->parent->right = replacement;
} else {
root = replacement;
}
if (replacement)
replacement->parent = node->parent;
delete node;
}
}
// Splay the given node.
// If a single rotation needs to be performed, perform it as the last rotation
// (i.e., to move the splayed node to the root of the tree).
virtual void splay(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;
}
}
};
#include <algorithm>
#include <cassert>
#include <fstream>
#include <functional>
#include <string>
#include <utility>
#include <vector>
#include "splay_operation.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);
// Flatten the tree: return a sorted list of all keys in the tree.
vector<int> flatten(const Tree& tree) {
constexpr int L = 0, R = 1, F = 2;
Node* node = tree.root;
vector<int> flattened, stack = {L};
while (!stack.empty()) {
if (stack.back() == L) {
stack.back() = R;
if (node->left) {
node = node->left;
stack.push_back(L);
}
} else if (stack.back() == R) {
flattened.push_back(node->key);
stack.back() = F;
if (node->right) {
node = node->right;
stack.push_back(L);
}
} else {
node = node->parent;
stack.pop_back();
}
}
return flattened;
}
// Test for splay operation with required helpers
class TestSplay {
public:
static Node* deserialize_node(const string& text, int& index) {
EXPECT(text[index++] == '(', "Internal error during example deserialization");
if (text[index] == ')') {
index++;
return nullptr;
} else {
int comma = text.find(',', index);
int key = stoi(text.substr(index, comma - index));
Node* left = deserialize_node(text, (index=comma + 1));
Node* right = deserialize_node(text, ++index);
EXPECT(text[index++] == ')', "Internal error during example deserialization");
return new Node(key, nullptr, left, right);
}
}
static Node* deserialize_root(const string& text) {
int index = 0;
Node* root = deserialize_node(text, index);
assert(index == text.size());
return root;
}
static string compare(Node* system, Node* gold) {
if (!system && gold) {
return "expected node with key " + to_string(gold->key) + ", found None";
} else if (system && !gold) {
return "expected None, found node with key " + to_string(system->key);
} else if (system && gold) {
if (system->key != gold->key)
return "expected node with key " + to_string(gold->key) + ", found " + to_string(system->key);
auto result = compare(system->left, gold->left);
if (!result.empty()) return result;
return compare(system->right, gold->right);
}
return string();
}
static void test() {
ifstream splay_tests_file("splay_tests.txt");
EXPECT(splay_tests_file.is_open(), "Cannot open splay_tests.txt file with the tests");
string original, splayed;
int target;
while (splay_tests_file >> original >> target >> splayed) {
Tree original_tree(deserialize_root(original));
Tree splayed_tree(deserialize_root(splayed));
Node* target_node = original_tree.root;
while (target_node && target_node->key != target)
if (target < target_node->key)
target_node = target_node->left;
else
target_node = target_node->right;
EXPECT(target_node, "Internal error during finding the target node in the tree to splay");
original_tree.splay(target_node);
auto error = compare(original_tree.root, splayed_tree.root);
EXPECT(error.empty(), "Error running splay on key " + to_string(target) + " of " + original + ": " + error);
}
}
};
void test_lookup() {
// Insert even numbers
Tree tree;
for (int i = 0; i < 5000000; i += 2)
tree.insert(i);
// Find non-existing
for (int i = 1; i < 5000000; i += 2)
for (int j = 0; j < 10; j++)
EXPECT(!tree.lookup(i), "Non-existing element was found");
// Find existing
for (int i = 0; i < 5000000; i += 2)
for (int j = 0; j < 10; j++)
EXPECT(tree.lookup(i), "Existing element was not found");
}
void test_insert() {
// Test validity first
{
Tree tree;
vector<int> sequence = {997};
for (int i = 2; i < 1999; i++)
sequence.push_back((sequence.back() * sequence.front()) % 1999);
for (const auto& i : sequence)
tree.insert(i);
vector<int> flattened = flatten(tree);
sort(sequence.begin(), sequence.end());
EXPECT(flattened == sequence, "Incorrect tree after a sequence of inserts");
}
// Test speed
{
Tree tree;
for (int i = 0; i < 5000000; i++)
for (int j = 0; j < 10; j++)
tree.insert(i);
}
}