Créer une structure de données Arborescente à partir d'une table en Java


Étant donné le CSV suivant, qui représente une hiérarchie de généralisation (pensez: anonymisation du code postal, par exemple dans la deuxième étape, le code postal 46072 devient 460** ):

A1, A*, *
A2, A*, *
A3, A*, *
B1, B*, *
B2, B*, *
B3, B*, *
B4, B*, *

Je crée un tableau de tableaux en l'analysant d'abord.

Je voudrais maintenant transformer cela en une représentation arborescente:

                *

        /                \

      A*                 B*

   /  |   \         /   |   |   \

 A1   A2   A3     B1   B2   B3  B4

Comme vous pouvez le voir, c'est un arbre avec chaque nœud ayant une quantité arbitraire d'enfants.

J'ai les classes suivantes:

Tableau , TableRow, TableCell ainsi que Arbre et Node. Évidemment, un tableau a plusieurs lignes, qui à leur tour ont plusieurs cellules. Un arbre est un nœud racine et un nœud a diverses opérations telles que addChild(nœud), getParent(), getChildren() etc.

J'essaie de comprendre, comment itérer sur ma table, afin d'étendre un arbre comme illustré ci-dessus. Jusqu'à présent, je ne me suis conduit que dans la confusion...

L'aide est beaucoup apprécié!

Author: pkluz, 2014-10-19

1 answers

OK. Donc, je fonde ma réponse sur ces hypothèses:

  1. La colonne la plus à droite de la matrice a toujours la même valeur tout au long.
  2. Toutes les lignes ont exactement le même nombre de colonnes.
  3. mêmes valeurs dans la Même colonne sont en lignes consécutives. Autrement dit, il n'y aura pas de ligne "A*" suivie d'un "B*" puis de nouveau par "A*". Les deux "A*" doivent être consécutifs.
  4. Dans la colonne la plus à gauche, toutes les valeurs sont uniques.

Je ne savais pas quelles sont exactement vos classes Table, Tree et Node peuvent ou ne peuvent pas faire. J'ai donc travaillé avec un tableau 2d de base (que vous avez également dit être ce que vous avez après l'analyse), et j'ai utilisé juste un nœud rudimentaire comme structure arborescente.

L'idée est de travailler récursivement à partir de la matrice head. Récursivité et arbre vont bien ensemble...

L'arbre est défini comme ayant la valeur de la colonne la plus à droite comme valeur racine, et ses enfants sont créés de la même manière en éliminant la colonne la plus à droite, et couper la matrice en morceaux de telle sorte que la colonne la plus à droite de ces morceaux ait une valeur identique. La matrice

A1, A*, *
A2, A*, *
A3, A*, *
B1, B*, *
B2, B*, *
B3, B*, *
B4, B*, *

Est divisé en une valeur "*" et les deux sous-matrices:

A1, A*
A2, A*
A3, A*

B1, B*
B2, B*
B3, B*
B4, B*

La même chose est faite pour la matrice A*, et ses sous-matrices sont des matrices unicellulaires, A1, A2 et A3, à quel point la récursivité se termine.

, en supposant que vous avez créé une classe qui représente une hiérarchie builder, et vous avez un tableau 2D appelé data, vous aurez une belle publics méthode sans paramètres, qui appelle une "sale" méthode privée qui possède des paramètres représentant les limites de la matrice pour la sous-matrice.

public Node<String> createTree() {
    return this.createTree(0,data.length-1,data[0].length-1);
}

Les arguments qu'il transmet à la méthode privée sont la ligne supérieure, la ligne inférieure, la colonne la plus à gauche et la colonne la plus à droite. Seulement puisque dans ce cas une sous-matrice commence toujours à partir de la colonne 0, nous n'avons pas besoin de passer la colonne la plus à gauche comme paramètre.

Et ceci est votre méthode privée createTree:

private Node<String> createTree( int firstRow, int lastRow, int lastCol) {

    // Recursion end. If we are at the leftmost column, just return a simple
    // node with the value at the current row and column.
    if ( lastCol == 0 ) {
        return new Node<String>( data[firstRow][0] );
    }

    // Create a node with the value of the top-right cell in our range.
    Node<String> result = new Node<String>(data[firstRow][lastCol]);

    // The next column from the right will have the values for the child nodes.
    // Split it into ranges (start row -> end row) and recursively build
    // the tree over the sub-matrix that goes column 0 -> lastCol-1 over each
    // range of rows.

    int childFirstRow = firstRow;
    String childVal = data[firstRow][lastCol-1];

    for( int candidateRow = firstRow; candidateRow <= lastRow; candidateRow ++ ) {
        // If the next value in the column is different from what we had so far, it's
        // the end of a row range, build the child tree, and mark this row as
        // the beginning of the next range.
        if ( ! data[candidateRow][lastCol-1].equals(childVal) ) {
            result.addChild(createTree( childFirstRow, candidateRow - 1, lastCol - 1));
            childFirstRow = candidateRow;
            childVal = data[childFirstRow][lastCol-1];
        }
        // In the special case of the last row, it's always the end of a range.
        if ( candidateRow == lastRow ) {
            result.addChild(createTree(childFirstRow,lastRow,lastCol - 1));
        }
    }

    return result;
}
 1
Author: RealSkeptic, 2014-10-19 22:30:55