简体   繁体   中英

Hierarchy data structure wih efficient query algorithm

I am looking for a data structure to represent hierarchy class system in Java. For example, I have three class, University,Major,Student, and their relationship looks like below. 在此处输入图片说明

Is there a efficient data structure that I can query with a path-like expression? For example, if the expression is CMU/cs/jake,then I get a instance of student class whose name is jake. As far as I know, the Trie could do this, is there any other option?

If your data fits into memory then you can implement this by putting a Set of children in each node of the hierarchy and then walking the sets to determine if the path is valid, for example

class University {
  private Set<Major> majors;
}

class Major {
  private Set<Student> students;
}

class Main {
  // true if the path is valid, else false
  public boolean query(University university, Major major, Student student) {
    return university.getMajors().contains(major) &&
      major.getStudents().contains(student);
  }
}

If you also need to walk the reverse path (ie if you need a bidirectional hierarchy) then you can put a Set of parents in each child.

This will run in average case O(d) where d is the depth of the hierarchy if you use HashSets , and in worst case O(d * lg(n)) where n is the size of the sets if you use TreeSets .

If your data doesn't fit into memory then you may want to consider using a graph database, eg Neo4j .


Edit: You can make the code more generic at the cost of type safety by using Map<String, E> at each level, assuming that each object has a unique name or some other string identifier.

abstract class Hierarchical<E extends Hierarchical> {
  protected final Map<String, E> children;

  public boolean query(Queue<String> query) {
    String key = query.poll();
    if(key != null) {
      E value = map.get(key);
      if(value != null) {
        return query.isEmpty() || value.contains(query);
      }
    }
    return false;
  }
}

class University extends Hierarchical<Major> {}

class Major extends Hierarchical<Student> {}

// special case for the bottom of the hierarchy
class Student extends Hierarchical<Hierarchical> {
  public Student() {
    children = null;
  }

  @Override
  public boolean query(Queue<String> query) {
    throw new UnsupportedOperationException("query should never reach this depth");
  }
}

class Main {
  // true if the path is valid, else false
  public boolean query(Hierarchial root, Queue<String> query) {
    return root.contains(query);
  }
}

This has the same runtime depending on whether you use a HashMap or TreeMap . The query only consists of a queue of strings; at each level of the hierarchy the first string is removed, the Map is queried and the child node is returned if found, and the query proceeds on to the child node until the queue is empty (return true) or a node isn't found (return false).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM