Last active
April 2, 2020 17:44
-
-
Save samloeschen/111f3ad57d6824ecbd1973316a69ef76 to your computer and use it in GitHub Desktop.
simple implementation of a Sparse Set in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#include <stdio.h> | |
#include "sparseset.h" | |
int min(int a, int b) { | |
return a < b ? a : b; | |
} | |
int max(int a, int b) { | |
return a > b ? a : b; | |
} | |
void makeSparseSet(int maxValue, int capacity, SparseSet *set) { | |
set->sparse = calloc(maxValue + 1, sizeof(int)); | |
set->dense = calloc(capacity, sizeof(int)); | |
set->count = 0; | |
set->capacity = capacity; | |
set->maxValue = maxValue; | |
} | |
int setContains(int x, SparseSet *set) { | |
if (x > set->maxValue) { | |
return -1; | |
} | |
int *dense = set->dense; | |
int *sparse = set->sparse; | |
int count = set->count; | |
if (sparse[x] < count && dense[sparse[x]] == x) { | |
return sparse[x]; | |
} | |
return -1; //not found | |
} | |
int setAdd(int x, SparseSet *set) { | |
if (x > set->maxValue) { | |
return -1; | |
} | |
if (set->count >= set->capacity) { | |
return -1; // set would overflow | |
} | |
if (setContains(x, set) != -1) { // set already contains value | |
return -1; | |
} | |
int *dense = set->dense; | |
int *sparse = set->sparse; | |
int count = set->count; | |
dense[count] = x; | |
sparse[x] = count; | |
set->count++; | |
return 0; | |
} | |
int setRemove(int x, SparseSet *set) { | |
if (setContains(x, set)) { | |
return -1; | |
} | |
int count = set->count; | |
int *dense = set->dense; | |
int *sparse = set->sparse; | |
int temp = dense[count - 1]; | |
dense[sparse[x]] = temp; | |
sparse[temp] = sparse[x]; | |
set->count--; | |
return 0; | |
} | |
void setIntersection(SparseSet *a, SparseSet *b, SparseSet *result) { | |
int capacity = min(a->capacity, b->capacity); | |
int maxValue = max(a->maxValue, b->maxValue); | |
makeSparseSet(maxValue, capacity, result); | |
int *dense; | |
int count; | |
SparseSet *targetSet; | |
if (a->count < b->count) { | |
dense = a->dense; | |
count = a->count; | |
targetSet = b; | |
} else { | |
dense = b->dense; | |
count = b->count; | |
targetSet = a; | |
} | |
for (int i = 0; i < count; i++) { | |
if (setContains(dense[i], targetSet) != -1) { | |
setAdd(dense[i], result); | |
} | |
} | |
} | |
void setUnion(SparseSet *a, SparseSet *b, SparseSet *result) { | |
int capacity = a->count + b->count; | |
int maxValue = max(a->maxValue, b->maxValue); | |
makeSparseSet(maxValue, capacity, result); | |
for (int i = 0; i < a->count; i++) { | |
setAdd(a->dense[i], result); | |
} | |
for (int i = 0; i < b->count; i++) { | |
setAdd(b->dense[i], result); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef SPARSE_SET_H | |
#define SPARSE_SET_H | |
typedef struct SparseSet { | |
int *sparse; | |
int *dense; | |
int count; | |
int capacity; | |
int maxValue; | |
} SparseSet; | |
void makeSparseSet(int maxValue, int capacity, SparseSet *set); | |
void setIntersection(SparseSet *a, SparseSet *b, SparseSet *result); | |
void setUnion(SparseSet *a, SparseSet *b, SparseSet *result); | |
int setContains(int x, SparseSet *set); | |
int setAdd(int x, SparseSet *set); | |
int setRemove(int x, SparseSet *set); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment