85 lines
2.2 KiB
C
85 lines
2.2 KiB
C
#ifndef INCLUDED_C_QUICKFINDUF_H
|
|||
|
|
#define INCLUDED_C_QUICKFINDUF_H
|
||
|
|
|
||
|
|
#ifndef INCLUDED_C_TYPES_H
|
||
|
|
#include <c_Types.h>
|
||
|
|
#endif /*INCLUDED_C_TYPES_H*/
|
||
|
|
|
||
|
|
#ifndef INCLUDED_C_ALLOCATOR_H
|
||
|
|
#include <c_Allocator.h>
|
||
|
|
#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; i<n; i++) {
|
||
|
|
self->id[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; i<self->n; 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*/
|