diff --git a/misc/cantor_set.c b/misc/cantor_set.c index a5d3e6b7..ff3b40fc 100644 --- a/misc/cantor_set.c +++ b/misc/cantor_set.c @@ -1,54 +1,61 @@ +/** + * @file + * @brief function to generate [Cantor ternary + * set](https://en.wikipedia.org/wiki/Cantor_set) + */ #include #include #include -struct contour +/** structure to define Cantor set */ +typedef struct contour { - double start; - double end; - struct contour *next; -}; -typedef struct contour Contour; -Contour *head; - -void startList(double start_num, double end_num) -{ - if (head == NULL) - { - head = (Contour *)malloc(sizeof(Contour)); - head->start = start_num; - head->end = end_num; - head->next = NULL; - } -} + double start; /**< start of interval */ + double end; /**< end of interval */ + struct contour *next; /**< pointer to next set */ +} Contour; +/** Iterative constructor of all sets in the current level. This function + * dynamically allocates memory when creating new sets. These are freed by the + * function ::free_memory. + * @param head pointer to interval set instance to update + */ void propagate(Contour *head) { - Contour *temp = head; - - if (temp != NULL) - { - Contour *newNode = (Contour *)malloc(sizeof(Contour)); - double diff = (((temp->end) - (temp->start)) / 3); - - newNode->end = temp->end; - temp->end = ((temp->start) + diff); - newNode->start = (newNode->end) - diff; - - newNode->next = temp->next; - - temp->next = newNode; - - propagate(temp->next->next); - } - else + // if input is NULL, ignore the process + if (head == NULL) return; + + Contour *temp = head; // local pointer to track propagation + + // create new node for the new set + Contour *newNode = (Contour *)malloc(sizeof(Contour)); + + // get 1/3rd of interval + double diff = (((temp->end) - (temp->start)) / 3); + + // update interval ranges + newNode->end = temp->end; + temp->end = ((temp->start) + diff); + newNode->start = (newNode->end) - diff; + + // update pointer to next set in this level + newNode->next = temp->next; + + // point to next set + temp->next = newNode; + + // create next set + propagate(temp->next->next); } +/** Print sets in the current range to `stdout` + * @param head pointer to first set in the current level + */ void print(Contour *head) { Contour *temp = head; - while (temp != NULL) + while (temp != NULL) // print while a valid set is found { printf("\t"); printf("[%lf] -- ", temp->start); @@ -59,10 +66,23 @@ void print(Contour *head) printf("\n"); } +/** Clear memory allocated by ::propagate function. + * @param head pointer to first allocated instance. + */ +void free_memory(Contour *head) +{ + if (!head) + return; + + if (head->next) + free_memory(head->next); + + free(head); +} + +/** Main function */ int main(int argc, char const *argv[]) { - head = NULL; - int start_num, end_num, levels; if (argc < 2) @@ -77,17 +97,27 @@ int main(int argc, char const *argv[]) levels = atoi(argv[3]); } - startList(start_num, end_num); + if (start_num < 0 || end_num < 0 || levels < 0) + { + fprintf(stderr, "All numbers must be positive\n"); + return -1; + } + Contour head = {.start = start_num, .end = end_num, .next = NULL}; + + // loop to propagate each level from top to bottom for (int i = 0; i < levels; i++) { printf("Level %d\t", i); - print(head); - propagate(head); + print(&head); + propagate(&head); printf("\n"); } printf("Level %d\t", levels); - print(head); + print(&head); + + // delete all memory allocated + free_memory(head.next); return 0; }