Files
Graph_Theory_Using_Flat_Buf…/Graph.cpp

149 lines
4.1 KiB
C++

#include "Graph.h"
// Begin : Construction & Deconstruction
Graph::Graph(size_t max_points, size_t max_edges) noexcept
{
all_points = new(std::nothrow) Point[max_points] {};
all_edges = new(std::nothrow) Edge[max_edges] {};
if(all_points && all_edges)
{
p_capacity = max_points;
e_capacity = max_edges;
}
}
Graph::~Graph()
{
delete[] all_points;
delete[] all_edges;
}
Graph::Graph(Graph&& new_location) noexcept
: all_points(std::exchange(new_location.all_points, nullptr)),
all_edges(std::exchange(new_location.all_edges, nullptr)),
p_capacity(std::exchange(new_location.p_capacity, 0)),
e_capacity(std::exchange(new_location.e_capacity, 0)) {}
// End : Construction & Deconstruction
// ----------------------- BEGIN : Getters -----------------------
Point* Graph::get_points() noexcept
{
return all_points;
}
Edge* Graph::get_p_edges(int p_index) noexcept
{
if(p_index < 0 || (size_t)p_index >= p_capacity) return nullptr;
int head_idx = all_points[p_index].first_edge;
if(head_idx == -1) return nullptr;
return &all_edges[head_idx];
}
// ----------------------- END : Getters -----------------------
// ----------------------- BEGIN : Mutators -----------------------
Point* Graph::add_point(std::string name, float x, float y, float z) noexcept {
int target_idx = -1;
if (next_free_point != -1) {
target_idx = next_free_point;
// The hijacked 'first_edge' tells us where the NEXT hole is
next_free_point = all_points[target_idx].first_edge;
}
else if (num_points < p_capacity) {
target_idx = (int)num_points;
num_points++;
}
else return nullptr;
Point* p = &all_points[target_idx];
p->name = name;
p->x = x; p->y = y; p->z = z;
p->first_edge = -1;
p->e_count = 0;
return p;
}
bool Graph::delete_point(int p_index) {
if (p_index < 0 || (size_t)p_index >= p_capacity) return false;
// 1. IMPORTANT: Clean up all edges belonging to this point first!
// While the point has edges, delete the 'end_point' of the first edge.
while (all_points[p_index].first_edge != -1) {
int target_end = all_edges[all_points[p_index].first_edge].end_point;
delete_edge(p_index, target_end);
}
// 2. Hijack point for Free List
all_points[p_index].first_edge = next_free_point;
all_points[p_index].e_count = -1;
next_free_point = p_index;
return true;
}
Edge* Graph::add_edge(int e_start, int e_end, float weight) noexcept {
// Validation: Ensure indices are within bounds
if (e_start < 0 || (size_t)e_start >= p_capacity ||
e_end < 0 || (size_t)e_end >= p_capacity) return nullptr;
int target_edge = -1;
if (next_free_edge != -1) {
target_edge = next_free_edge;
next_free_edge = all_edges[target_edge].next_edge;
}
else if (num_edges < e_capacity) {
target_edge = (int)num_edges;
num_edges++;
}
else return nullptr;
// Initialize and Link
all_edges[target_edge].end_point = e_end;
all_edges[target_edge].e_weight = weight;
// Link to Point's head
all_edges[target_edge].next_edge = all_points[e_start].first_edge;
all_points[e_start].first_edge = target_edge;
all_points[e_start].e_count++;
return &all_edges[target_edge];
}
bool Graph::delete_edge(int e_start, int e_end) noexcept {
Point& p = all_points[e_start];
int current = p.first_edge;
int prev = -1;
// 1. Traverse the linked list of edges for this point
while (current != -1) {
if (all_edges[current].end_point == e_end) {
// 2. Unhook the node
if (prev == -1) p.first_edge = all_edges[current].next_edge;
else all_edges[prev].next_edge = all_edges[current].next_edge;
// 3. Add the edge slot back to the global free list
all_edges[current].next_edge = next_free_edge;
next_free_edge = current;
p.e_count--;
return true;
}
prev = current;
current = all_edges[current].next_edge;
}
return false;
}
// ----------------------- END : Mutators -----------------------