Task 10 exercise a

This commit is contained in:
Jan-Niclas Loosen
2026-01-26 22:40:07 +01:00
parent 90ce78f17d
commit b8a2972b6b
5 changed files with 392 additions and 1 deletions

206
Uebung-10/main.cpp Normal file
View File

@@ -0,0 +1,206 @@
#include <vector>
#include <queue>
#include <cstdint>
#include <random>
#include <stdexcept>
#include <iostream>
#include "BitVector.hpp"
// ==========================================
// Aufgabenteil a) Baseline-Implementierung
// ==========================================
class BaselineTree {
public:
struct Node {
uint32_t parent = 0; // 0 = Root
std::vector<uint32_t> children;
};
private:
std::vector<Node> nodes;
public:
BaselineTree() {
nodes.emplace_back();
nodes.emplace_back();
}
static int32_t root() {
return 1;
}
[[nodiscard]] uint64_t nodeCount() const {
return nodes.size() - 1;
}
[[nodiscard]] const std::vector<uint32_t>& children(const uint32_t id) const {
return nodes[id].children;
}
[[nodiscard]] uint32_t parent(const uint32_t id) const {
return nodes[id].parent;
}
[[nodiscard]] bool exists(const uint32_t id) const {
return id > 0 && id < nodes.size();
}
uint32_t add(const uint32_t parentId) {
if (!exists(parentId)) {
throw std::invalid_argument("parentId does not exist");
}
nodes.emplace_back();
const uint32_t id = nodes.size() - 1;
nodes[id].parent = parentId;
nodes[parentId].children.push_back(id);
return id;
}
// BFS traversing with lambda for increased reusability
template<typename Fn>
void bfs(Fn&& fn) const {
std::queue<uint32_t> q;
q.push(root());
while (!q.empty()) {
uint32_t u = q.front();
q.pop();
fn(u, nodes[u]);
for (uint32_t v : nodes[u].children) {
q.push(v);
}
}
}
[[nodiscard]] uint64_t sizeInBytes() const {
uint64_t total = 0;
// Size of data in the tree instance
total += sizeof(BaselineTree);
total += nodes.capacity() * sizeof(Node);
// Size of data in node instances
bfs([&](uint32_t, const Node& n) {
total += n.children.capacity() * sizeof(uint32_t);
});
return total;
}
static BaselineTree randomTree(const uint64_t N, const uint32_t seed = 03062001) {
BaselineTree t;
t.nodes.reserve(N + 1);
std::mt19937 gen(seed);
for (uint32_t i = 2; i <= N; ++i) {
std::uniform_int_distribution<uint32_t> dist(1, i - 1);
t.add(dist(gen));
}
return t;
}
};
// ==========================================
// Aufgabenteil b) LOUDS-Implementierung
// ==========================================
class LOUDSTree {
// Der BitVector ist der einzige Datenspeicher! Keine Knoten-Objekte.
BitVector bv;
public:
// TODO: Passen Sie den Konstruktor an Ihre BaselineTree-Klasse an.
// Der Konstruktor soll den übergebenen Baum in Level-Order traversieren
// und die LOUDS-Bits in 'bv' setzen.
explicit LOUDSTree(const BaselineTree &tree) : bv(1 /* TODO: Richtige Größe berechnen! */) {
// TODO: Implementierung der LOUDS-Erstellung (BFS Traversierung)
// TODO: bfs can be used here! Comment by JNLOOS
// WICHTIG: Am Ende muss der Index gebaut werden:
bv.buildIndex();
}
uint64_t sizeInBytes() const {
return bv.sizeInBytes();
}
// --- LOUDS-Operationen (Ausschließlich via rank/select implementieren!) ---
uint64_t parent(uint64_t i) {
// TODO
return 0;
}
bool isRoot(uint64_t i) {
// TODO
return false;
}
bool isLeaf(uint64_t i) {
// TODO
return false;
}
uint64_t outDegree(uint64_t i) {
// TODO
return 0;
}
uint64_t childNum(uint64_t i, uint64_t j) {
// TODO: Geben Sie das j-te Kind von nodeId zurück (j ist 1-basiert)
return 0;
}
};
int main() {
// Parameter für den Benchmark, 1 Million Knoten
const uint64_t N = 1000000;
std::cout << "--- Start der Uebung: LOUDS (N=" << N << ") ---" << std::endl;
// 1. Baseline Tree erstellen
std::cout << "[Init] Erstelle Baseline Tree..." << std::endl;
// Nutzen Sie std::mt19937 für reproduzierbare Zufallszahlen.
const BaselineTree baseline = BaselineTree::randomTree(N);
// 2. LOUDS Tree erstellen
// std::cout << "[Init] Konvertiere zu LOUDS..." << std::endl;
// const LOUDSTree louds(baseline);
// 3. Speichermessung
const uint64_t bytesBaseline = baseline.sizeInBytes();
// uint64_t bytesLouds = louds.sizeInBytes();
std::cout << "Speicher Baseline: " << bytesBaseline / (1024.0 * 1024.0) << " MB" << std::endl;
// std::cout << "Speicher LOUDS: " << bytesLouds / (1024.0 * 1024.0) << " MB" << std::endl;
// if (bytesLouds > 0) {
// std::cout << "Faktor: " << (double) bytesBaseline / bytesLouds << "x" << std::endl;
// }
// 4. Laufzeitmessung (Parent Operation)
// std::cout << "[Benchmark] Starte 1.000.000 Parent-Abfragen..." << std::endl;
// uint64_t checksum = 0;
// auto start = std::chrono::high_resolution_clock::now();
// for (uint64_t i = 2; i <= N; ++i) {
// checksum += louds.parent(i);
// }
// auto end = std::chrono::high_resolution_clock::now();
// auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
// std::cout << "Zeit LOUDS: " << duration << " ms" << std::endl;
// std::cout << "Checksum: " << checksum << std::endl;
return 0;
}