learning-cc4e

Solution to https://cc4e.com/. If you copy these you're not right in the head.
git clone https://kaka.farm/~git/learning-cc4e
Log | Files | Refs

solution.c (6369B)


      1 /* You have to build everything except the main program here 
      2  * You should not need to write any new code - just gather your 
      3  * working TreeMap code and the supplied code together from the previous
      4  * assignment and combine them together.
      5  */
      6 
      7 struct TreeMapEntry {
      8   char *key;  /* public */
      9   int value;  /* public */
     10   struct TreeMapEntry *__next;
     11   struct TreeMapEntry *__left;
     12   struct TreeMapEntry *__right;
     13 };
     14 
     15 struct TreeMapIter {
     16   struct TreeMapEntry *__current;
     17 
     18   struct TreeMapEntry* (*next)(struct TreeMapIter* self);
     19   void (*del)(struct TreeMapIter* self);
     20 };
     21 
     22 struct TreeMap {
     23   /* Attributes */
     24   struct TreeMapEntry *__head;
     25   struct TreeMapEntry *__root;
     26   int __count;
     27   int debug;
     28 
     29   /* Methods */
     30   void (*put)(struct TreeMap* self, char *key, int value);
     31   int (*get)(struct TreeMap* self, char *key, int def);
     32   int (*size)(struct TreeMap* self);
     33   void (*dump)(struct TreeMap* self);
     34   struct TreeMapIter* (*iter)(struct TreeMap* self);
     35   void (*del)(struct TreeMap* self);
     36 };
     37 
     38 void __TreeMap_del(struct TreeMap* self) {
     39   struct TreeMapEntry *cur, *next;
     40   cur = self->__head;
     41   while(cur) {
     42     free(cur->key);
     43     /* value is just part of the struct */
     44     next = cur->__next;
     45     free(cur);
     46     cur = next;
     47   }
     48   free((void *)self);
     49 }
     50 
     51 void __TreeMapIter_del(struct TreeMapIter* self) {
     52   free((void *)self);
     53 }
     54 
     55 void __TreeMap_dump_tree(struct TreeMapEntry *cur, int depth)
     56 {
     57   int i;
     58   if ( cur == NULL ) return;
     59   for(i=0;i<depth;i++) printf("| ");
     60   printf("%s=%d\n", cur->key, cur->value);
     61   if ( cur->__left != NULL ) {
     62     __TreeMap_dump_tree(cur->__left, depth+1);
     63   }
     64   if ( cur->__right != NULL ) {
     65     __TreeMap_dump_tree(cur->__right, depth+1);
     66   }
     67 }
     68 
     69 void __TreeMap_dump(struct TreeMap* self)
     70 {
     71   struct TreeMapEntry *cur;
     72   printf("Object TreeMap count=%d\n", self->__count);
     73   for(cur = self->__head; cur != NULL ; cur = cur->__next ) {
     74     printf("  %s=%d\n", cur->key, cur->value);
     75   }
     76   printf("\n");
     77   __TreeMap_dump_tree(self->__root, 0);
     78   printf("\n");
     79 }
     80 
     81 /* Run a check to see if left and right are broken */
     82 void __Map_check(struct TreeMap* self, struct TreeMapEntry *left, char *key, struct TreeMapEntry *right)
     83 {
     84   if ( self->debug ) 
     85     printf("Check position: %s < %s > %s\n", (left ? left->key : "0"),
     86            key, (right ? right->key : "0") );
     87 
     88   /* Check our location in the linked list */
     89   if ( left != NULL ) {
     90     if ( left->__next != right ) {
     91       printf("FAIL left->__next != right\n");
     92     }
     93   } else {
     94     if ( self->__head != right ) {
     95       printf("FAIL self->__head != right\n");
     96     }
     97   }
     98 
     99   /* Check our location in the tree */
    100   if ( right != NULL && right->__left == NULL ) {
    101     /* OK */
    102   } else if ( left != NULL && left->__right == NULL ) {
    103     /* OK */
    104   } else {
    105     printf("FAIL Neither right->__left nor left->__right are available\n");
    106   }
    107 }
    108 
    109 void __TreeMap_put(struct TreeMap* self, char *key, int value) {
    110   struct TreeMapEntry *cur, *left, *right;
    111   int cmp;
    112   struct TreeMapEntry *old, *new;
    113   char *new_key;
    114 
    115   cur = self->__root;
    116   left = NULL;
    117   right = NULL;
    118 
    119   /* TODO: Loop through the tree from the root.  If the matches
    120    * the node, update the value and return.  Ad the tree is scanned,
    121    * keep track of the node containing largest key less than "key"
    122    * in the variable left and the node containing the smallest key
    123    * greater than "key" in the variable "right".  So if the key is
    124    * not found, left will be the closest lower neighbor or null
    125    * and right will be the closest greater neighbor or null.
    126    */
    127 
    128   while (cur != NULL) {
    129     cmp = strcmp(key, cur->key);
    130     if (cmp == 0) {
    131       cur->value = value;
    132       return;
    133     }
    134 
    135     old = cur;
    136 
    137     if (cmp < 0) {
    138       right = cur;
    139       cur = cur->__left;
    140     }
    141 
    142     if (cmp > 0) {
    143       left = cur;
    144       cur = cur->__right;
    145     }
    146   }
    147 
    148   ++self->__count;
    149 
    150   /* Not found - time to insert into the linked list after old */
    151   new = malloc(sizeof(*new));
    152 
    153   /* TODO: Set up the new node with its new data. */
    154   new_key = malloc(sizeof(*new_key) * (strlen(key) + 1));
    155   new_key = strcpy(new_key, key);
    156   new->key = new_key;
    157   new->value = value;
    158   new->__next = NULL;
    159   new->__left = NULL;
    160   new->__right = NULL;
    161 
    162   /* Empty list - add first entry */
    163   if ( self->__head == NULL ) {
    164     self->__head = new;
    165     self->__root = new;
    166     return;
    167   }
    168 
    169   /* Keep this in here - it will help you debug the above code */
    170   __Map_check(self, left, key, right);
    171 
    172   /* TODO: Insert into the sorted linked list */
    173   if (left == NULL) {
    174     new->__next = self->__head;
    175     self->__head = new;
    176   } else if (right == NULL) {
    177     left->__next = new;
    178   } else {
    179     new->__next = right;
    180     left->__next = new;
    181   }
    182 
    183   /* TODO: Insert into the tree */
    184   if (cmp > 0) {
    185     old->__right = new;
    186   } else {
    187     old->__left = new;
    188   }
    189 }
    190 
    191 int __TreeMap_get(struct TreeMap* self, char *key, int def)
    192 {
    193   int cmp;
    194   struct TreeMapEntry *cur;
    195 
    196   if ( self == NULL || key == NULL || self->__root == NULL ) return def;
    197 
    198   cur = self->__root;
    199 
    200   /* TODO: scan down the tree and if the key is found, return the value.
    201    * If the key is not found, return the default value (def).
    202    */
    203 
    204   while (cur != NULL) {
    205     cmp = strcmp(key, cur->key);
    206     if (cmp == 0) {
    207       return cur->value;
    208     } else if (cmp < 0) {
    209       cur = cur->__left;
    210     } else {
    211       cur = cur->__right;
    212     }
    213   }
    214 
    215   return def;
    216 }
    217 
    218 struct TreeMapEntry* __TreeMapIter_next(struct TreeMapIter* self)
    219 {
    220   /* Advance the iterator.  Recall that when we first
    221    * create the iterator __current points to the first item
    222    * so we must return an item and then advance the iterator.
    223    */
    224   struct TreeMapEntry *cur = self->__current;
    225   if (self->__current != NULL) {
    226     self->__current = cur->__next;
    227   }
    228   return cur;
    229 }
    230 
    231 int __TreeMap_size(struct TreeMap* self)
    232 {
    233   return self->__count;
    234 }
    235 
    236 struct TreeMapIter* __TreeMap_iter(struct TreeMap* self)
    237 {
    238   struct TreeMapIter *iter = malloc(sizeof(*iter));
    239   iter->__current = self->__head;
    240   iter->next = &__TreeMapIter_next;
    241   iter->del = &__TreeMapIter_del;
    242   return iter;
    243 }
    244 
    245 struct TreeMap * TreeMap_new() {
    246   struct TreeMap *p = malloc(sizeof(*p));
    247 
    248   p->__head = NULL;
    249   p->__root = NULL;
    250   p->__count = 0;
    251   p->debug = 0;
    252 
    253   p->put = &__TreeMap_put;
    254   p->get = &__TreeMap_get;
    255   p->size = &__TreeMap_size;
    256   p->dump = &__TreeMap_dump;
    257   p->iter = &__TreeMap_iter;
    258   p->del = &__TreeMap_del;
    259   return p;
    260 }