// Laboratorio 8 - Esercizio 3 - ExrateBST.c // Matteo Schiff - s295565 #include #include "ExrateBST.h" typedef struct node *link; struct node { Exrate exrate; int N; link left, right; }; struct exrateBST { link root; link z; int N; }; static link createNode(Exrate exrate, link l, link r, int N) { link new = malloc(sizeof(*new)); new->exrate = exrate; new->left = l; new->right = r; new->N = N; return new; } static link rotR(link n) { link t = n->left; n->left = t->right; t->right = n; t->N = n->N; n->N = 1; n->N += (n->left) ? n->left->N : 0; n->N += (n->right) ? n->right->N : 0; return t; } static link rotL(link h) { link t = h->right; h->right = t->left; t->left = h; t->N = h->N; h->N = 1; h->N += (h->left) ? h->left->N : 0; h->N += (h->right) ? h->right->N : 0; return t; } ExrateBST ExrateBSTCreate() { ExrateBST new = malloc(sizeof(*new)); new->z = createNode(ExrateEmpty(), NULL, NULL, 0); new->root = new->z; return new; } static void freeBST(link n, link z) { if (n == z) return; free(n->left); free(n->right); free(n); } void ExrateBSTFree(ExrateBST ebst) { freeBST(ebst->root, ebst->z); free(ebst->z); free(ebst); } static link search(link n, DateTime dt, link z) { if (n == z) return z; int c = DateTimeCompare(dt, n->exrate.datetime); if (c == 0) return n; if (c > 0) return search(n->right, dt, z); else return search(n->left, dt, z); } Exrate ExrateBSTSearch(ExrateBST ebst, DateTime dt) { // nota: se search restituisce z, allora z,exrate è l'exrate nullo return search(ebst->root, dt, ebst->z)->exrate; } static void ExrateBSTInsertLeaf(ExrateBST ebst, Exrate exrate) { if (ebst->root == ebst->z) { ebst->root = createNode(exrate, ebst->z, ebst->z, 1); ebst->N++; return; } link *n = &ebst->root; while (*n != ebst->z) { (*n)->N++; if (DateTimeCompare(exrate.datetime, (*n)->exrate.datetime) > 0) { n = &(*n)->right; } else { n = &(*n)->left; } } *n = createNode(exrate, ebst->z, ebst->z, 1); ebst->N++; } void ExrateBSTInsert(ExrateBST ebst, Exrate exrate) { link node = search(ebst->root, exrate.datetime, ebst->z); if (node != ebst->z) { // Merge exrate node->exrate.q = ((node->exrate.n * node->exrate.q) + (exrate.n * exrate.q)) / (node->exrate.n + exrate.n); node->exrate.n += exrate.n; } else { ExrateBSTInsertLeaf(ebst, exrate); } } static void mergeR(ExrateBST dst, link r, link z) { if (r == z) return; mergeR(dst, r->left, z); mergeR(dst, r->right, z); ExrateBSTInsert(dst, r->exrate); } void ExrateBSTMerge(ExrateBST dst, ExrateBST src) { mergeR(dst, src->root, src->z); } static void getMaxMinLengthR(link n, link z, int *min, int *max, int *counter) { if (n == z) { if (*counter < *min) *min = *counter; if (*counter > *max) *max = *counter; return; } (*counter)++; getMaxMinLengthR(n->left, z, min, max, counter); getMaxMinLengthR(n->right, z, min, max, counter); (*counter)--; } static int getMaxMinDiff(ExrateBST ebst) { int counter = 0, min = ebst->N, max = 0; getMaxMinLengthR(ebst->root, ebst->z, &min, &max, &counter); return max - min; } link partR(link h, int r) { int t = h->left->N; if (t > r) { h->left = partR(h->left, r); h = rotR(h); } if (t < r) { h->right = partR(h->right, r - t - 1); h = rotL(h); } return h; } static link balanceR(link h, link z) { int r; if (h == z) return z; r = (h->N + 1) / 2 - 1; h = partR(h, r); h->left = balanceR(h->left, z); h->right = balanceR(h->right, z); return h; } void visitInOrderCheckInterval(link h, link z, DateTime dt1, DateTime dt2, int interval, Exrate *min, Exrate *max) { if (h == z) return; visitInOrderCheckInterval(h->left,z,dt1,dt2,interval,min,max); if (!interval || (DateTimeCompare(h->exrate.datetime, dt1) >= 0 && DateTimeCompare(h->exrate.datetime, dt2) <= 0)) { if (h->exrate.q > max->q) *max = h->exrate; if (h->exrate.q < max->q) *min = h->exrate; } visitInOrderCheckInterval(h->right,z,dt1,dt2,interval,min,max); } void ExrateBSTBalance(ExrateBST bst) { // calcola la differenza (distanza root -> nodo massima) - (distanza root -> nodo minima) int diff = getMaxMinDiff(bst); if (diff >= S) { printf("La differenza tra il cammino più corto e quello più lungo è di %d, bilancio l'albero...\n", diff); bst->root = balanceR(bst->root, bst->z); diff = getMaxMinDiff(bst); printf("Bilanciato, ora la differenza è di: %d\n", diff); } else { printf("La differenza tra il cammino più corto e quello più lungo è di %d, non è necessario bilanciare l'albero\n", diff); } } void ExrateBSTMinMaxW(ExrateBST bst, DateTime dt1, DateTime dt2, int interval) { Exrate min, max; min = max = bst->root->exrate; visitInOrderCheckInterval(bst->root, bst->z, dt1, dt2, interval, &min, &max); printf("Quotazione minima: "); ExratePrint(min); printf("Quotazione massima: "); ExratePrint(max); } void ExrateBSTMinMax(ExrateBST bst) { DateTime empty; ExrateBSTMinMaxW(bst, empty, empty, 0); } void ExrateBSTMinMaxInInterval(ExrateBST bst, DateTime dt1, DateTime dt2) { ExrateBSTMinMaxW(bst, dt1, dt2, 1); }