#include #include #include #include #include struct quadtree { int type; /* BLACK, WHITE oder SPLIT */ int size; /* Immer eine Zweierpotenz! */ struct quadtree * children[4]; }; /* Kontanten fuer quadtree->type */ #define BLACK 0 #define WHITE 1 #define SPLIT 2 /* Konstanten fuer die Indices in quadtree->children[] */ #define UL 0 /* Upper Left, links oben */ #define UR 1 /* Upper Right, rechts oben */ #define LL 2 /* Lower Left, links unten */ #define LR 3 /* Lower Right, rechts unten */ /* root is ein quadtree, i und j sind Zeilen- und Spaltennnummer eines Pixels. get_child_idx liefert den index des quadtree in root->children, in dem sich das durch i und j angegebene Pixel befindet. */ int get_child_idx (struct quadtree * root, int i, int j) { int size = root->size; if (i < size/2) { if (j < size/2) { return UL; } return UR; } if (j < size/2) { return LL; } return LR; } /* Plaziere ein weisses Pixel in Zeile i, Spalte j des quadtree root */ void put (struct quadtree * root, int i, int j) { int idx, x; assert (isize && j < root->size); /* Der ganze Baum ist schon weiss? Fertig. */ if (root->type == WHITE) { return; } /* Ein Baum der groesse 1? Einfach nur die Farbe in WHITE aendern. */ if (root->size == 1) { root->type = WHITE; return; } /* Wenn der Baum noch keine Kinder hat, bekommt er 4 Kinder, die alle die selbe Farbe haben, wie im Moment ganze Baum. Der Baum selbst ist anschliessend natuerlich vom Typ SPLIT. */ if (root->type != SPLIT) { for (x=0; x<4; ++x) { root->children[x] = calloc (1, sizeof (struct quadtree)); root->children[x]->type = root->type; root->children[x]->size = root->size/2; } root->type = SPLIT; } /* In welchem der Kinder liegt das Pixel (i,j)? */ idx = get_child_idx (root, i, j); /* Koordinaten relativ zu diesem Kind berechnen. */ i %= (root->size/2); j %= (root->size/2); /* Rekursiver Aufruf. */ put (root->children[idx], i, j); /* Sind jetzt alle Kinder weiss? */ for (x=0; x<4; ++x) { if (root->children[x]->type != WHITE) { return; } } /* Falls ja: Kinder freigeben und root zu selbst zu einem * Knoten vom Typ WHITE machen. */ for (x=0; x<4; ++x) { free (root->children[x]); root->type = WHITE; } } /* Liefert die Farbe des Pixels (i,j) zurueck */ int get (struct quadtree * root, int i, int j) { int idx; assert (i < root->size && j < root->size); if (root->type != SPLIT) { return root->type; } assert (root->size >= 2); idx = get_child_idx (root, i, j); i %= (root->size/2); j %= (root->size/2); return get (root->children[idx], i, j); } /* Gibt einen Baum als String aus. */ void print_tree (struct quadtree * root) { int x; if (root->type == BLACK) { printf ("B"); return ; } if (root->type == WHITE) { printf ("W"); return ; } printf ("["); for (x=0; x<4; ++x) { print_tree (root->children[x]); } printf ("]"); } /* Gibt mit Hilfe von get() einen Baum als Bild aus. */ void print_image (struct quadtree * root) { int i, j; printf ("\n"); for (i=0; isize; ++i) { for (j=0; jsize; ++j) { switch (get (root, i, j)) { case BLACK: printf ("#"); break; case WHITE: printf (" "); break; } } printf ("\n"); } } int main () { struct quadtree * root = calloc (1, sizeof (struct quadtree)); char buf[100], cmd[100]; /* Anfangs ist das ganze Bild schwarz. */ root->type = BLACK; scanf ("%d ", &root->size); /* Die Groesse muss eine Zweierpotenz sein! */ { int tmpsize = root->size; while (tmpsize) { assert (tmpsize == 1 || (tmpsize & 1) == 0); tmpsize >>= 1; } } /* Kommandos lesen, bis das Dateiende erreicht ist. */ while (1) { int i, j; fgets (buf, 100, stdin); if (feof (stdin)) break; if (sscanf (buf, "%s %d %d", cmd, &i, &j) == 3) { if (strcasecmp (cmd, "PUT") == 0) { put (root, i, j); continue; } } if (strcasecmp (buf, "PRINT TREE\n") == 0) { print_tree (root); printf ("\n"); continue; } if (strcasecmp (buf, "PRINT IMAGE\n") == 0) { print_image (root); sleep (1); continue; } fprintf (stderr, "Unknown command\n"); } return 0; }