267 lines
5.6 KiB
C
267 lines
5.6 KiB
C
// Laboratorio 8 - Esercizio 3 - ExrateBST.c
|
|
// Matteo Schiff - s295565
|
|
|
|
#include <stdlib.h>
|
|
#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);
|
|
}
|