Skip to content
Advertisement

Determine paths through elements

I have a class Item, which uses a character as identifier.

public class Item {

    private char identifier;
    private Set<Character> predecessors;
    private Set<Character> successors;

    // Constructor, getters and setters...

}

I would like to be able to retrieve the paths, represented by the Path class, which contains a simple ordered list of Item :

public class Path {

    private List<Item> items;

    // Constructor, getters and setters 

}

To store and manage my items and paths, I use a dedicated class. It contains two Set containing each of these types. I can retrieve a task using its identifier.

public class SimpleClass {

    private Set<Item> items;
    private Set<Path> paths;

    // Constructor, getters and setters

    public Optional<Item> getItemById(char identifier) {
        /// ....
    }

}

I would like to create a method to return a Set containing every Path but I can’t do it. A little help would be welcome. A small example to illustrate my point:

Graph example

  • D and E are the antecedents of G
  • G is a successor of D and E
  • A, B, D, G, J, K is a path
  • A, C, F, H, J, K is a path

Update / Note: I am looking to build the paths through the set of items

Advertisement

Answer

A quick and dirty recursive algorithm. I just create the first map to speed up Item retrieval. See if it works, try to understand it and change it.

/**
 * Build all paths
 */
public void buildPaths() {
    Map<Character,Item> itemsByID=new HashMap<>();
    for (Item i:items) {
        itemsByID.put(i.getIdentifier(), i);
    }
    List<Item> starts=items.stream().filter(i->i.getPredecessors().isEmpty()).collect(Collectors.toList());
    for (Item st:starts) {
        Path p=new Path();
        p.getItems().add(st);
        buildPath(p,itemsByID);
    }
}

/**
 * Build the next step of the given path
 * @param p
 * @param itemsByID
 */
private void buildPath(Path p,Map<Character,Item> itemsByID) {
    Item last=p.getItems().get(p.getItems().size()-1);
    Set<Character> successors=last.getSuccessors();
    // no successor, path is finished, add to collection
    if (successors.isEmpty()) {
        paths.add(p);
    // one successor continue on same path
    } else if (successors.size()==1){
        p.getItems().add(itemsByID.get(successors.iterator().next()));
        buildPath(p,itemsByID);
    } else {
        // multiple successors, create a new path for each branch
        for (Character c:successors) {
            Path p1=new Path();
            p1.getItems().addAll(p.getItems());
            p1.getItems().add(itemsByID.get(c));
            buildPath(p1, itemsByID);
        }
    }
}
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement