learning-cc4e

Solution to https://cc4e.com/. If you copy these you're not right in the head.
Log | Files | Refs

commit 4875c6b899dcedcfb5cc886b9980258776686acb
parent 44d6b874ddf2dbaa34e7d8e09f9487b97224627a
Author: Yuval Langer <yuval.langer@gmail.com>
Date:   Thu,  2 Nov 2023 10:32:16 +0200

Add LinkedTreeMap exercise.

Diffstat:
Mhash-map/solution.c | 1+
Alinked-tree-map/main.c | 175+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alinked-tree-map/output.txt | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Alinked-tree-map/solution.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alinked-tree-map/student.c | 2++
Alinked-tree-map/template.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 355 insertions(+), 0 deletions(-)

diff --git a/hash-map/solution.c b/hash-map/solution.c @@ -79,6 +79,7 @@ struct HashMapEntry* __HashMapIter_next(struct HashMapIter* self) while (self->__current == NULL) { if (self->__bucket >= self->__map->__buckets) { + /* Avoids counting unnecessarily. */ return NULL; } ++self->__bucket; diff --git a/linked-tree-map/main.c b/linked-tree-map/main.c @@ -0,0 +1,175 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +struct TreeMapEntry { + char *key; /* public */ + int value; /* public */ + struct TreeMapEntry *__next; + struct TreeMapEntry *__left; + struct TreeMapEntry *__right; +}; + +struct TreeMapIter { + struct TreeMapEntry *__current; + + struct TreeMapEntry* (*next)(struct TreeMapIter* self); + void (*del)(struct TreeMapIter* self); +}; + +struct TreeMap { + /* Attributes */ + struct TreeMapEntry *__head; + struct TreeMapEntry *__root; + int __count; + int debug; + + /* Methods */ + void (*put)(struct TreeMap* self, char *key, int value); + int (*get)(struct TreeMap* self, char *key, int def); + int (*size)(struct TreeMap* self); + void (*dump)(struct TreeMap* self); + struct TreeMapIter* (*iter)(struct TreeMap* self); + void (*del)(struct TreeMap* self); +}; + +void __TreeMap_del(struct TreeMap* self) { + struct TreeMapEntry *cur, *next; + cur = self->__head; + while(cur) { + free(cur->key); + /* value is just part of the struct */ + next = cur->__next; + free(cur); + cur = next; + } + free((void *)self); +} + +void __TreeMapIter_del(struct TreeMapIter* self) { + free((void *)self); +} + +void __TreeMap_dump_tree(struct TreeMapEntry *cur, int depth) +{ + int i; + if ( cur == NULL ) return; + for(i=0;i<depth;i++) printf("| "); + printf("%s=%d\n", cur->key, cur->value); + if ( cur->__left != NULL ) { + __TreeMap_dump_tree(cur->__left, depth+1); + } + if ( cur->__right != NULL ) { + __TreeMap_dump_tree(cur->__right, depth+1); + } +} + +void __TreeMap_dump(struct TreeMap* self) +{ + struct TreeMapEntry *cur; + printf("Object TreeMap count=%d\n", self->__count); + for(cur = self->__head; cur != NULL ; cur = cur->__next ) { + printf(" %s=%d\n", cur->key, cur->value); + } + printf("\n"); + __TreeMap_dump_tree(self->__root, 0); + printf("\n"); +} + +/* Run a check to see if left and right are broken */ +void __Map_check(struct TreeMap* self, struct TreeMapEntry *left, char *key, struct TreeMapEntry *right) +{ + if ( self->debug ) + printf("Check position: %s < %s > %s\n", (left ? left->key : "0"), + key, (right ? right->key : "0") ); + + /* Check our location in the linked list */ + if ( left != NULL ) { + if ( left->__next != right ) { + printf("FAIL left->__next != right\n"); + } + } else { + if ( self->__head != right ) { + printf("FAIL self->__head != right\n"); + } + } + + /* Check our location in the tree */ + if ( right != NULL && right->__left == NULL ) { + /* OK */ + } else if ( left != NULL && left->__right == NULL ) { + /* OK */ + } else { + printf("FAIL Neither right->__left nor left->__right are available\n"); + } +} + +#include "student.c" + +int __TreeMap_size(struct TreeMap* self) +{ + return self->__count; +} + +struct TreeMapIter* __TreeMap_iter(struct TreeMap* self) +{ + struct TreeMapIter *iter = malloc(sizeof(*iter)); + iter->__current = self->__head; + iter->next = &__TreeMapIter_next; + iter->del = &__TreeMapIter_del; + return iter; +} + +struct TreeMap * TreeMap_new() { + struct TreeMap *p = malloc(sizeof(*p)); + + p->__head = NULL; + p->__root = NULL; + p->__count = 0; + p->debug = 0; + + p->put = &__TreeMap_put; + p->get = &__TreeMap_get; + p->size = &__TreeMap_size; + p->dump = &__TreeMap_dump; + p->iter = &__TreeMap_iter; + p->del = &__TreeMap_del; + return p; +} + +int main(void) +{ + struct TreeMap * map = TreeMap_new(); + struct TreeMapEntry *cur; + struct TreeMapIter *iter; + + setvbuf(stdout, NULL, _IONBF, 0); /* Internal */ + + map->debug = 1 == 1; + + printf("Testing TreeMap\n"); + map->put(map, "h", 42); + map->put(map, "d", 8); + map->put(map, "f", 5); + map->put(map, "b", 123); + map->dump(map); + map->put(map, "k", 9); + map->put(map, "m", 67); + map->put(map, "j", 12); + map->put(map, "f", 6); + map->dump(map); + + printf("r=%d\n", map->get(map, "r", 42)); + printf("x=%d\n", map->get(map, "x", 42)); + + printf("\nIterate\n"); + iter = map->iter(map); + while(1) { + cur = iter->next(iter); + if ( cur == NULL ) break; + printf(" %s=%d\n", cur->key, cur->value); + } + iter->del(iter); + + map->del(map); +} diff --git a/linked-tree-map/output.txt b/linked-tree-map/output.txt @@ -0,0 +1,48 @@ +output from your program: + +Testing TreeMap +Check position: 0 < d > h +Check position: d < f > h +Check position: 0 < b > d +Object TreeMap count=4 + b=123 + d=8 + f=5 + h=42 + +h=42 +| d=8 +| | b=123 +| | f=5 + +Check position: h < k > 0 +Check position: k < m > 0 +Check position: h < j > k +Object TreeMap count=7 + b=123 + d=8 + f=6 + h=42 + j=12 + k=9 + m=67 + +h=42 +| d=8 +| | b=123 +| | f=6 +| k=9 +| | j=12 +| | m=67 + +r=42 +x=42 + +Iterate + b=123 + d=8 + f=6 + h=42 + j=12 + k=9 + m=67 +\ No newline at end of file diff --git a/linked-tree-map/solution.c b/linked-tree-map/solution.c @@ -0,0 +1,64 @@ +void __TreeMap_put(struct TreeMap* self, char *key, int value) { + struct TreeMapEntry *cur, *left, *right; + int cmp; + struct TreeMapEntry *old, *new; + char *new_key; + + cur = self->__root; + left = NULL; + right = NULL; + + /* TODO: Loop through the tree from the root. If the matches + * the node, update the value and return. Ad the tree is scanned, + * keep track of the node containing largest key less than "key" + * in the variable left and the node containing the smallest key + * greater than "key" in the variable "right". So if the key is + * not found, left will be the closest lower neighbor or null + * and right will be the closest greater neighbor or null. + */ + + /* Not found - time to insert into the linked list after old */ + new = malloc(sizeof(*new)); + + /* TODO: Set up the new node with its new data. */ + + /* Empty list - add first entry */ + if ( self->__head == NULL ) { + self->__head = new; + self->__root = new; + return; + } + + /* Keep this in here - it will help you debug the above code */ + __Map_check(self, left, key, right); + + /* TODO: Insert into the sorted linked list */ + + /* TODO: Insert into the tree */ + +} + +int __TreeMap_get(struct TreeMap* self, char *key, int def) +{ + int cmp; + struct TreeMapEntry *cur; + + if ( self == NULL || key == NULL || self->__root == NULL ) return def; + + cur = self->__root; + + /* TODO: scan down the tree and if the key is found, return the value. + * If the key is not found, return the default value (def). + */ + + return def; +} + +struct TreeMapEntry* __TreeMapIter_next(struct TreeMapIter* self) +{ + /* Advance the iterator. Recall that when we first + * create the iterator __current points to the first item + * so we must return an item and then advance the iterator. + */ + return NULL; +} diff --git a/linked-tree-map/student.c b/linked-tree-map/student.c @@ -0,0 +1 @@ +solution.c +\ No newline at end of file diff --git a/linked-tree-map/template.c b/linked-tree-map/template.c @@ -0,0 +1,64 @@ +void __TreeMap_put(struct TreeMap* self, char *key, int value) { + struct TreeMapEntry *cur, *left, *right; + int cmp; + struct TreeMapEntry *old, *new; + char *new_key; + + cur = self->__root; + left = NULL; + right = NULL; + + /* TODO: Loop through the tree from the root. If the matches + * the node, update the value and return. Ad the tree is scanned, + * keep track of the node containing largest key less than "key" + * in the variable left and the node containing the smallest key + * greater than "key" in the variable "right". So if the key is + * not found, left will be the closest lower neighbor or null + * and right will be the closest greater neighbor or null. + */ + + /* Not found - time to insert into the linked list after old */ + new = malloc(sizeof(*new)); + + /* TODO: Set up the new node with its new data. */ + + /* Empty list - add first entry */ + if ( self->__head == NULL ) { + self->__head = new; + self->__root = new; + return; + } + + /* Keep this in here - it will help you debug the above code */ + __Map_check(self, left, key, right); + + /* TODO: Insert into the sorted linked list */ + + /* TODO: Insert into the tree */ + +} + +int __TreeMap_get(struct TreeMap* self, char *key, int def) +{ + int cmp; + struct TreeMapEntry *cur; + + if ( self == NULL || key == NULL || self->__root == NULL ) return def; + + cur = self->__root; + + /* TODO: scan down the tree and if the key is found, return the value. + * If the key is not found, return the default value (def). + */ + + return def; +} + +struct TreeMapEntry* __TreeMapIter_next(struct TreeMapIter* self) +{ + /* Advance the iterator. Recall that when we first + * create the iterator __current points to the first item + * so we must return an item and then advance the iterator. + */ + return NULL; +}