Task 10 exercise a
This commit is contained in:
206
Uebung-10/main.cpp
Normal file
206
Uebung-10/main.cpp
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user