diff --git a/Makefile b/Makefile index 4d5185b..c053061 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ all: clear build launch -TARGET_DZ = 4 +TARGET_DZ = 3 TARGET_RK = D diff --git a/README.md b/README.md index 9835861..5936c80 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ 7 - 3 - YES +RK - 1 - YES + https://contest.yandex.ru/contest/36255/enter ### Module 2 @@ -32,5 +34,13 @@ https://contest.yandex.ru/contest/36255/enter 5 - all - +RK - 1 - YES + +RK - 2 - YES + +RK - 3 - YES + +RK - 4 - YES/NO + https://contest.yandex.ru/contest/37595/enter/ \ No newline at end of file diff --git a/module_2/3.cpp b/module_2/3.cpp new file mode 100644 index 0000000..dd3b3a1 --- /dev/null +++ b/module_2/3.cpp @@ -0,0 +1,251 @@ +#include +#include +#include +#include + + +// Постройте B-дерево минимального порядка t и выведите его по слоям. +// В качестве ключа используются числа, лежащие в диапазоне 0..2^32 -1 + +template +struct Node { + bool leaf; + + std::vector keys; + std::vector children; + + Node(bool leaf) : leaf(leaf) {} + + ~Node(); + + friend std::ostream& operator<<(std::ostream &os, const Node &it) { + for (auto &data: it.keys) { + os << data << " "; + } + + return os; + } + + Node &operator = (const Node &other) = default; +}; + +template +Node::~Node() { + for (auto child: children) { + delete child; + } +} + +template +class Less { +public: + bool operator()(const T &l, const T &r) const { + return l < r; + } +}; + +template> +class BTree { + CompareRule rule; + + size_t t; + + size_t size; + + Node *root; + + bool IsNodeFull(Node *node); + + void SplitChild(Node *node, size_t index); + + void AddNonFull(Node *node, const T &data); + + void DebugPrint(Node *node, size_t indent); + +public: + BTree(const size_t min_degree) : t(min_degree), root(nullptr), size(0) { assert(min_degree >= 2); } + + ~BTree(); + + void Add(const T &data); + + void DebugPrint(); + + void Print(); + + size_t Size() const; +}; + +template +void BTree::Print() { + std::queue < Node * > s; + + s.push(root); + + while (!s.empty()) { + Node *tmp = s.front(); + s.pop(); + + std::cout << *tmp; + + for (size_t i = 0; i < tmp->children.size(); ++i) { + s.push(tmp->children[i]); + } + } +} + +template +void BTree::SplitChild(Node *node, size_t index) { + Node *new_child = new Node(node->children[index]->leaf); + ++size; + + for (size_t i = 0; i < t - 1; ++i) { + new_child->keys.push_back(node->children[index]->keys[i + t]); + } + + for (size_t i = 0; i < t - 1; ++i) { + node->children[index]->keys.pop_back(); + } + + ssize_t pos = node->keys.size() - 1; + + T mid = node->children[index]->keys[t - 1]; + + node->keys.resize(node->keys.size() + 1); + while (pos >= 0 && mid < node->keys[pos]) { + node->keys[pos + 1] = node->keys[pos]; + + --pos; + } + + node->keys[pos + 1] = mid; + + if (!node->children[index]->leaf) { + size_t count_child = node->children[index]->children.size() - 1; + + for (size_t i = 0; i < t; ++i) { + new_child->children.push_back(node->children[index]->children[i + t]); + } + + + for (size_t i = 0; i < t; ++i) { + node->children[index]->children.pop_back(); + } + } + + node->children[index]->keys.pop_back(); + + node->children.push_back(new_child); +} + +template +void BTree::DebugPrint() { + DebugPrint(root, 0); +} + +template +void BTree::DebugPrint(Node *node, size_t indent) { + std::cout << std::string(indent, ' '); + std::cout << "data: ["; + + for (auto it = node->keys.begin(); it != node->keys.end(); it++) { + std::cout << (*it); + if (it + 1 != node->keys.end()) + std::cout << ", "; + } + + std::cout << "]" << std::endl; + + for (auto child: node->children) { + DebugPrint(child, indent + 4); + } +} + +template +BTree::~BTree() { + if (root) { + delete root; + } +} + +template +bool BTree::IsNodeFull(Node *node) { + return node->keys.size() == 2 * t - 1; +} + +template +void BTree::Add(const T &data) { + if (!root) { + root = new Node(true); + ++size; + } + + if (IsNodeFull(root)) { + Node *new_root = new Node(false); + ++size; + + new_root->children.push_back(root); + + root = new_root; + + SplitChild(root, 0); + } + + AddNonFull(root, data); +} + +template +void BTree::AddNonFull(Node *node, const T &data) { + ssize_t pos = node->keys.size() - 1; + + if (node->leaf) { + node->keys.resize(node->keys.size() + 1); + + while (pos >= 0 && data < node->keys[pos]) { + node->keys[pos + 1] = node->keys[pos]; + + --pos; + } + + node->keys[pos + 1] = data; + } else { + while (pos >= 0 && data < node->keys[pos]) { + --pos; + } + + if (IsNodeFull(node->children[pos + 1])) { + SplitChild(node, pos + 1); + + if (data > node->keys[pos + 1]) { + ++pos; + } + } + + AddNonFull(node->children[pos + 1], data); + } +} + + +void run(std::istream &input, std::ostream &output) { + size_t n; + + input >> n; + + BTree b_tree(n); + + size_t tmp; + + while (input >> tmp) { + b_tree.Add(tmp); + } + + b_tree.DebugPrint(); + + b_tree.Print(); +} + +int main() { + run(std::cin, std::cout); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/module_2/Tests/3/1.txt b/module_2/Tests/3/1.txt new file mode 100644 index 0000000..b0613f1 --- /dev/null +++ b/module_2/Tests/3/1.txt @@ -0,0 +1,2 @@ +2 +0 1 2 3 4 5 6 7 8 9 diff --git a/module_2/Tests/3/2.txt b/module_2/Tests/3/2.txt new file mode 100644 index 0000000..2ee689e --- /dev/null +++ b/module_2/Tests/3/2.txt @@ -0,0 +1,2 @@ +4 +0 1 2 3 4 5 6 7 8 9 \ No newline at end of file