#13

// itbl.h --- int table api.
struct itbl;
typedef struct itbl *itblp;
itblp itbl_new();                     // allocate new tbl
void itbl_put(itblp t, int k, int v); // store value
int itbl_get(itblp t, int k);         // obtain value
//void itbl_delete(itblp t, int k);     // delete key/value
void itbl_pr(itblp t);                // print contents
// bstree.c --- itbl impl with binary search tree.
#include <stdlib.h>
#include <stdio.h>
#include "itbl.h"
typedef struct ent *entp;
struct ent { int key, val; entp left, right; };
struct itbl { entp root; };
itblp itbl_new() {
  itblp p = (itblp)malloc(sizeof(struct itbl));
  p->root = NULL; return p;
}
static int get(entp p, int k) {
  if(p == NULL) { return -1; }
  if(k == p->key) { return p->val; }
  return get((k < p->key) ? p->left : p->right, k);
}
int itbl_get(itblp p, int k) { return get(p->root, k); }
static void put(entp *p, int k, int v) {
  if(*p == NULL) {
    entp q = *p = (entp)malloc(sizeof(struct ent));
    q->left = q->right = NULL; q->key = k; q->val = v;
  } else if(k == (*p)->key) {
    (*p)->val = v;
  } else {
    put((k < (*p)->key) ? &((*p)->left) : &((*p)->right), k, v);
  }
}
void itbl_put(itblp p, int k, int v) { put(&(p->root), k, v); }
static void pr(entp p) {
  if(p->left != NULL) { printf("("); pr(p->left); printf(") "); }
  printf("%d:%d", p->key, p->val);
  if(p->right != NULL) { printf(" ("); pr(p->right); printf(")"); }
}
void itbl_pr(itblp p) {
  if(p->root != NULL) { printf("("); pr(p->root); printf(")\n"); }
}
// treedemo.c --- demonstration of bstree operation
#include <stdlib.h>
#include <stdio.h>
#include "itbl.h"

int main(int argc, char *argv[]) {
  int n = atoi(argv[1]);
  itblp p = itbl_new();
  for(int i = 1; i < argc; ++i) {
    int v = atoi(argv[i]);
    if(v >= 0) { itbl_put(p, v, i); }
//  else       { itbl_delete(p, -v); }
    itbl_pr(p);
  }
  return 0;
}
// btree23.c --- itbl impl with 2-3 B-tree.
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include "itbl.h"
#define D 1
typedef struct ent *entp;
struct ent {
  bool leaf;
  int nkey, key[D*2+1], val[D*2+1];
  entp child[D*2+1];
};
struct itbl { entp root; };
itblp itbl_new() {
  itblp p = (itblp)malloc(sizeof(struct itbl));
  p->root = NULL; return p;
}
static int get(entp p, int k) {
  int i;
  for(i = 0; k >= p->key[i] && i < p->nkey; ++i) {
    if(k == p->key[i]) { return p->val[i]; }
  }
  return (p->leaf) ? -1 : get(p->child[i], k);
}
int itbl_get(itblp p, int k) {
  return (p->root == NULL) ? -1 : get(p->root, k);
}
static entp newent2(int k, int v, entp l, entp r) {
  entp p = (entp)malloc(sizeof(struct ent));
  p->leaf = false; p->nkey = 1; p->key[0] = k; p->val[0] = v;
  p->child[0] = l; p->child[1] = r; return p;
}
static entp newent(int k, int v) {
  entp q = newent2(k, v, NULL, NULL); q->leaf = true; return q;
}
static entp cpent2(entp p, int i, entp l, entp r) {
  entp q = newent2(p->key[i], p->val[i], l, r); return q;
}
static entp cpent(entp p, int i) {
  entp q = cpent2(p, i, NULL, NULL); q->leaf = true; return q;
}
static void shift(entp p, int i) {
  for(int j = ++p->nkey; j > i; --j) {
    p->key[j] = p->key[j-1]; p->val[j] = p->val[j-1];
    p->child[j] = p->child[j-1];
  }
}
static entp pleaf(entp p, int i, int k, int v) {
  if(p->nkey < D*2) { 
    shift(p, i); p->key[i] = k; p->val[i] = v; return NULL;
  } else if(i == 0) {
    return newent2(p->key[0], p->val[0], newent(k, v), cpent(p, 1));
  } else if(i == 1) {
    return newent2(k, v, cpent(p, 0), cpent(p, 1));
  } else {
    return newent2(p->key[1], p->val[1], cpent(p, 0), newent(k, v));
  }
}
static entp pnode(entp p, entp q, int i) {
  if(q == NULL) { return NULL; }
  entp r = NULL;
  if(p->nkey < D*2) {
    shift(p, i); p->key[i] = q->key[0]; p->val[i] = q->val[0];
    p->child[i] = q->child[0]; p->child[i+1] = q->child[1];
  } else if(i == 0) {
    r = newent2(p->key[0], p->val[0],
                newent2(q->key[0], q->val[0], q->child[0], q->child[1]),
                cpent2(p, 1, p->child[1], p->child[2]));
  } else if(i == 1) {
    r = newent2(q->key[0], q->val[0],
                cpent2(p, 0, p->child[0], q->child[0]),
                cpent2(p, 1, q->child[1], p->child[2]));
  } else {
    r = newent2(p->key[1], p->val[1],
                cpent2(p, 0, p->child[0], p->child[1]),
                newent2(q->key[0], q->val[0], q->child[0], q->child[1]));
  }
  free(q); return r;
}
static entp put(entp p, int k, int v) {
  int i;
  for(i = 0; k >= p->key[i] && i < p->nkey; ++i) {
    if(k == p->key[i]) { p->val[i] = v; return NULL; }
  }
  return p->leaf ? pleaf(p, i, k, v) : pnode(p, put(p->child[i], k, v), i);
}
void itbl_put(itblp p, int k, int v) {
  int k1, v1;
  if(p->root == NULL) { p->root = newent(k, v); return; }
  entp r = put(p->root, k, v);
  if(r != NULL) { free(p->root); p->root = r; }
}
static void pr(entp p) {
  int i;
  if(p == NULL) { printf("NULL"); return; }
  if(p->leaf) {
    if(p->nkey > 0) { printf("%d:%d", p->key[0], p->val[0]); }
    for(i = 1; i < p->nkey; ++i) {
      printf(" %d:%d", p->key[i], p->val[i]);
    }
  } else {
    for(i = 0; i < p->nkey; ++i) {
      printf("("); pr(p->child[i]);
      printf(") %d:%d ", p->key[i], p->val[i]);
    }
    printf("("); pr(p->child[i]); printf(")");
  }
}
void itbl_pr(itblp p) { printf("("); pr(p->root); printf(")\n"); }