#ifndef INCLUDED_C_QUICKFINDUF_H #define INCLUDED_C_QUICKFINDUF_H #ifndef INCLUDED_C_TYPES_H #include #endif /*INCLUDED_C_TYPES_H*/ #ifndef INCLUDED_C_ALLOCATOR_H #include #endif /*INCLUDED_C_ALLOCATOR_H*/ /* ------------------------------------------------------------------------------------------------------------------ */ /* */ typedef struct { c_size_t* id; c_size_t n; c_size_t count; c_Allocator_t allocator; }c_QuickFindUF_t; /* ------------------------------------------------------------------------------------------------------------------ */ /* */ C_STATIC_FORCE_INLINE c_err_t c_QuickFindUF_Init(c_QuickFindUF_t* self, c_size_t n, c_Allocator_t* allocator) { if (!self) return C_ERR_PARAM; self->allocator = allocator?*allocator:c_DefaultAllocator; self->n = n; self->id = c_Allocator_Alloc(&self->allocator, n * sizeof(*self->id)); if (!self->id) return C_ERR_NOMEM; self->count = n; for (c_size_t i=0; iid[i] = i; } return C_ERR_OK; } C_STATIC_FORCE_INLINE void c_QuickFindUF_Destroy(c_QuickFindUF_t* self) { if (!self) return; if (self->id) { c_Allocator_Free(&self->allocator, self->id); self->id = NULL; } self->n = 0; self->count = 0; } C_STATIC_FORCE_INLINE c_err_t c_QuickFindUF_Find(c_QuickFindUF_t* self, c_size_t p, c_size_t* out) { if (!self) return C_ERR_PARAM; if (p >= self->n) return C_ERR_OUTOFBOUND; if (out) { *out = self->id[p]; } return C_ERR_OK; } C_STATIC_FORCE_INLINE c_err_t c_QuickFindUF_Union(c_QuickFindUF_t* self, c_size_t p, c_size_t q) { if (!self) return C_ERR_PARAM; if (p >= self->n || q>=self->n) return C_ERR_OUTOFBOUND; c_size_t pID = self->id[p]; c_size_t qID = self->id[q]; if (pID == qID) return C_ERR_OK; for (c_size_t i=0; in; i++) { if (self->id[i] == pID) { self->id[i] = qID; } } self->count--; return C_ERR_OK; } C_STATIC_FORCE_INLINE bool c_QuickFindUF_IsConnected(c_QuickFindUF_t* self, c_size_t p, c_size_t q) { if (!self) return false; if (p >= self->n || q>=self->n) return false; return self->id[p] == self->id[q]; } #endif /*INCLUDED_C_QUICKFINDUF_H*/