neo4j遍历和图算法
2014-05-08 14:34
253 查看
这篇blog主要和大家分享一下neo4j中是如何对节点进行遍历,和其中集成的图论的一些常用算法。
遍历
http://docs.neo4j.org.cn/tutorials-java-embedded-traversal.html 这是neo4j官方的中文教程。
private static Traverser getFriends(Node node ) { TraversalDescription td = Traversal.description() .breadthFirst() .relationships( RelTypes.KNOWS, Direction.OUTGOING ) .evaluator( Evaluators.excludeStartPosition() ); return td.traverse( node ); }TraversalDescription提供了用户遍历节点的方法,并且用户需要自己添加遍历的条件。 首先用户可以定义是使用深度优先还收广度优先 breadthFirst() 和 depthFirst();relationships定义了遍历取得节点的关系类型,是入度Direction.INCOMING还是出度Direction.OUTGOING还是both;evaluator用来定义筛选的条件,比如去掉开始节点,结束节点,遍历深度(toDepth(3))等,具体可以参照官方的API文档。
int num = 0; String result = neoNode.getProperty( "name" ) + "'s friends:\n"; Traverser friendsTraverser = getFriends( neoNode ); for ( Path friendPath : friendsTraverser ) { output += "At depth " + friendPath.length() + " => " + friendPath.endNode() .getProperty( "name" ) + "\n"; numberOfFriends++; } output += "Number of friends found: " + numberOfFriends + "\n";打印出结果
Thomas Anderson's friends: At depth 1 => Trinity At depth 1 => Morpheus At depth 2 => Cypher At depth 3 => Agent Smith 找到朋友的数量: 4下面介绍如何按照一个预先定义好的顺序遍历图。 创建一个数据库
Node A = db.createNode(); Node B = db.createNode(); Node C = db.createNode(); Node D = db.createNode(); A.createRelationshipTo( B, REL1 ); B.createRelationshipTo( C, REL2 ); C.createRelationshipTo( D, REL3 ); A.createRelationshipTo( C, REL2 );现在关系(REL1-->REL2-->REL), 当遍历的时候,Evaluator能够对它进行检验,确保只有该关系顺序的路径才会被包括。
ArrayList<RelationshipType> orderedPathContext = new ArrayList<RelationshipType>(); orderedPathContext.add( REL1 ); orderedPathContext.add( withName( "REL2" ) ); orderedPathContext.add( withName( "REL3" ) ); TraversalDescription td = Traversal.description() .evaluator( new Evaluator() { @Override public Evaluation evaluate( final Path path ) { if ( path.length() == 0 ) { return Evaluation.EXCLUDE_AND_CONTINUE; } RelationshipType expectedType = orderedPathContext.get( path.length() - 1 ); boolean isExpectedType = path.lastRelationship() .isType( expectedType ); boolean included = path.length() == orderedPathContext.size() && isExpectedType; boolean continued = path.length() < orderedPathContext.size() && isExpectedType; return Evaluation.of( included, continued ); } } );打印出结果
Traverser traverser = td.traverse( A ); PathPrinter pathPrinter = new PathPrinter( "name" ); for ( Path path : traverser ) { output += Traversal.pathToString( path, pathPrinter ); }用户也可以通过自定义格式输出路径。
static class PathPrinter implements Traversal.PathDescriptor<Path> { private final String nodePropertyKey; public PathPrinter( String nodePropertyKey ) { this.nodePropertyKey = nodePropertyKey; } @Override public String nodeRepresentation( Path path, Node node ) { return "(" + node.getProperty( nodePropertyKey, "" ) + ")"; } @Override public String relationshipRepresentation( Path path, Node from, Relationship relationship ) { String prefix = "--", suffix = "--"; if ( from.equals( relationship.getEndNode() ) ) { prefix = "<--"; } else { suffix = "-->"; } return prefix + "[" + relationship.getType().name() + "]" + suffix; } }图算法
neo4j中集成了一些常用的图算法,包括最短路径,Dijkstra,A*算法。 最短路径
public Iterable<Path> findShortestPath(Node node1, Node node2) { PathFinder<Path> finder = GraphAlgoFactory.shortestPath( Traversal.expanderForTypes(RelTypes.KNOWS, Direction.BOTH), 10); Iterable<Path> paths = finder.findAllPaths(node1, node2); return paths; }
for(Path shortestPath: findShortestPath(aa, ab)) { System.out.println(shortestPath.toString()); }Traversal.expanderForTypes用来定义遍历的深度和节点关系的出入度。 Dijkstra解决有向图中任意两个顶点之间的最短路径问题。
PathFinder<WeightedPath> finder = GraphAlgoFactory.dijkstra( Traversal.expanderForTypes( ExampleTypes.MY_TYPE, Direction.BOTH ), "cost" ); WeightedPath path = finder.findSinglePath( nodeA, nodeB ); path.weight();使用 A*算法是解决静态路网中求解最短路最有效的方法。
Node nodeA = createNode( "name", "A", "x", 0d, "y", 0d ); Node nodeB = createNode( "name", "B", "x", 7d, "y", 0d ); Node nodeC = createNode( "name", "C", "x", 2d, "y", 1d ); Relationship relAB = createRelationship( nodeA, nodeC, "length", 2d ); Relationship relBC = createRelationship( nodeC, nodeB, "length", 3d ); Relationship relAC = createRelationship( nodeA, nodeB, "length", 10d ); EstimateEvaluator<Double> estimateEvaluator = new EstimateEvaluator<Double>() { public Double getCost( final Node node, final Node goal ) { double dx = (Double) node.getProperty( "x" ) - (Double) goal.getProperty( "x" ); double dy = (Double) node.getProperty( "y" ) - (Double) goal.getProperty( "y" ); double result = Math.sqrt( Math.pow( dx, 2 ) + Math.pow( dy, 2 ) ); return result; } }; PathFinder<WeightedPath> astar = GraphAlgoFactory.aStar( Traversal.expanderForAllTypes(), CommonEvaluators.doubleCostEvaluator( "length" ), estimateEvaluator ); WeightedPath path = astar.findSinglePath( nodeA, nodeB );阅读更多
相关文章推荐
- 二.从零写单链表的算法之遍历节点&删除节点&逆序节点
- 随机遍历数组,很巧妙的算法
- 用java代码实现二叉树的遍历算法
- 【算法入门经典】6.3.2 层次遍历二叉树【结构体指针】
- 【算法-java】判断该数组是不是某二叉搜索树的后序遍历的结果
- 第十一周项目1-(1)二叉树的层次遍历算法
- 算法:图的广度优先遍历(Breadth First Search)
- 算法中的一个模式:栈式遍历
- 算法:求幂集(回溯法与树的遍历)-数据结构(17)
- 第十周 数据结构例程——二叉树的层次遍历算法
- 【数据结构与算法】二叉树的层序遍历
- 遍历操作列表的算法
- 算法实验-二叉树的创建和前序-中序-后序-层次 遍历
- 笔试算法题(07):还原后序遍历数组 & 半翻转英文句段
- 数据结构和算法--二叉树创建和递归遍历
- 【数据结构与算法】二叉树前序、中序、后序遍历间关系
- 第十一周项目1-验证算法(1)-层次遍历算法的验证
- 第十一周项目一 层次遍历算法的验证
- (第十一周项目1)二叉树算法验证(1)层次遍历算法的验证
- 【LeetCode-面试算法经典-Java实现】【102-Binary Tree Level Order Traversal(二叉树层序遍历)】