Hackerrank solutions.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

155 lines
3.3 KiB

/*
* Simple integer interval tree implementation
* Kept sorted by interval starting point
* Not balanced
* Author: Titouan Rigoudy
*/
#include <stdlib.h>
#include <stdio.h>
#include "itree.h"
#define EVENTS_MIN_SIZE 1024
struct itree *itree_new(int i, int j, long v) {
struct itree *it = malloc(sizeof *it);
if (!it) {
return NULL;
}
it->i = i;
it->j = j;
it->v = v;
it->left = NULL;
it->right = NULL;
return it;
}
void itree_free(struct itree *it) {
if (!it) {
return;
}
itree_free(it->left);
itree_free(it->right);
free(it);
}
void itree_print(struct itree *it) {
if (!it) {
puts("NULL itree");
}
printf("itree{i: %d, j:%d, v:%ld}\n", it->i, it->j, it->v);
puts("Left:");
if (it->left) {
itree_print(it->left);
}
puts("Right:");
if (it->right) {
itree_print(it->right);
}
}
void itree_add(struct itree *it, int i, int j, long v) {
if (!it) {
fputs("Adding to null interval tree", stderr);
return;
}
if (it->i == i && it->j == j) {
it->v += v;
return;
}
if (i < it->i || (i == it->i && j <= it->j)) {
if (it->left) {
itree_add(it->left, i, j, v);
} else {
it->left = itree_new(i, j, v);
}
return;
}
if (it->right) {
itree_add(it->right, i, j, v);
} else {
it->right = itree_new(i, j, v);
}
}
// For use in qsort
int ieventcmp(const void *event1, const void *event2) {
const struct ievent *ev1 = event1;
const struct ievent *ev2 = event2;
return ev1->i - ev2->i;
}
// For debugging purposes
void ievent_print(const struct ievent ev) {
printf("ievent{i:%d, v:%ld}\n", ev.i, ev.v);
}
// Recursively add events from it to *events
// *events is of size *n, *i is the current number of events in *events
// Returns 0 on success, 1 on error
int itree_flatten_aux(
struct itree *it, struct ievent **events, int *n, int *i) {
if (!it) {
return 0;
}
int err = itree_flatten_aux(it->left, events, n, i);
if (err) {
return err;
}
free(it->left);
it->left = NULL;
if (*i == *n) {
// grow events
*n = *n * 2 + 2; // just in case n was 0
*events = realloc(*events, *n);
if (*events == NULL) {
return 1; // signal error
}
}
if (it->v != 0) {
// Add interval start event
(*events)[*i].i = it->i;
(*events)[*i].v = it->v;
(*i)++;
// Add interval end event
(*events)[*i].i = it->j;
(*events)[*i].v = -it->v;
(*i)++;
}
err = itree_flatten_aux(it->right, events, n, i);
if (err) {
return err;
}
free(it->right);
it->right = NULL;
it->v = 0;
return 0;
}
// Flatten the tree into a list of events representing
// interval start and end points
int itree_flatten(struct itree *it, struct ievent **events) {
int n = EVENTS_MIN_SIZE;
*events = malloc(n * sizeof(**events));
if (*events == NULL) {
return 0;
}
int i = 0;
int err = itree_flatten_aux(it, events, &n, &i);
if (err) {
*events = NULL;
return 0;
}
qsort(*events, i, sizeof(**events), ieventcmp);
return i;
}