Could somebody explain to me why this simple piece of code will not compile?
Node.groovy
class Node{
Integer key
String value
Node leftNode
Node rightNode
Node(){}
Node(Integer k, String v){
this.key = k
this.value = v
}
}
BinaryTree.groovy
class BinaryTree{
Node root;
def addNode(k, v){
def newNode = new Node(k,v)
if(!root){
root = newNode
}else{
Node currentNode = root
Node parent
while(true){
parent = currentNode
if(k < currentNode.key) {
currentNode = currentNode.leftNode
if(!currentNode){
parent.leftNode = newNode
return
}
} else {
currentNode = currentNode.rightNode
if(!currentNode){
parent.rightNode = newNode
return
}
}
}
}
}
def inOrderTraversal(def node, def silent){
if(node){
inOrderTraversal(node.leftNode)
!silent ?: println("Node ${node.dump()}")
inOrderTraversal(node.rightNode)
}
}
}
Main.groovy
//Test the binaryTree Project
binaryTree = new BinaryTree();
binaryTree.addNode(45, "v1")
binaryTree.addNode(60, "v4")
binaryTree.addNode(12, "v3")
binaryTree.addNode(32, "v9")
binaryTree.addNode(415, "v7")
binaryTree.inOrderTraversal(binaryTree.root, false)
3 simple files. This is that I get when I press play in intellij, or when I try to run this: groovy -cp ./src src/Main.groovy
Caught: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: groovy.util.Node(java.lang.Integer, java.lang.String)
groovy.lang.GroovyRuntimeException: Could not find matching constructor for: groovy.util.Node(java.lang.Integer, java.lang.String)
at BinaryTree.addNode(BinaryTree.groovy:7)
at BinaryTree$addNode.call(Unknown Source)
at Main.run(Main.groovy:4)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
The constructor in Node looks fine to me.
I am using Java 8 and groovy 2.4
Thanks
Related
I found this code on the web and I am trying to understand how it works.
public void insertFirst( int e )
{if(isEmpty())
{
head = trail = new DNode(e, null, null); //(data, prev, next)
}
else {
head.prev = new DNode(e, null, head);
head = head.prev;
}
size++;
}
In the first part of the code,
if(isEmpty())
{
head = trail = new DNode(e, null, null); //(data, prev, next)
}
This means that if the Doubly Linked List is empty, then create the Node that connects to prev null and next null. And then set that as head and trail.
And then the second part of code is,
else {
head.prev = new DNode(e, null, head);
head = head.prev;
}
I don't really understand how this works in the else statement.
Could you please explain this to me?
Thank you
If the list is empty, you just create a single node, which has no `prev` and no `next` elements.
If the list is not empty:
null <- [head] -> [node] ...
this is a structure of a non-empty head node.
If you insert a new head the algorithm is to:
[new_head] <- [head] // head.prev = new DNode(e, null, head);
in the constructor of DNode null means that a new_head has no prev element.
and head means that the next element of new_head is head.
BUT you haven't changed the head reference yet. So, you set a new head reference (= new_head) as head = head.prev; because head.prev == new_head.
I'll break it down a little and comment the code to explain it:
public void insertFirst(int e){
if(isEmpty()) {
// null <-prev-- [newHead(e)] --next-> null
DNode newHead = new DNode(e, null, null);
// list.head --> [newHead(e)] <-- list.trail
head = newHead;
trail = newHead;
} else {
// null <-prev-- [newHead(e)] --next-> [head(other_e)] . . .
DNode newHead = new DNode(e, null, head);
// [newHead(e)] <-prev-- [head(other_e)] . . .
head.prev = newHead;
// list.head --> [newHead(e)] . . .
head = head.prev; // since 'head.prev' holds 'newHead'
// now you have this:
// list.head -> [newHead(e)] --next-> [oldHead(other_e)] --next-> (.. maybe others ..) <-- list.trail
// [ ] <-prev-- [ ]
}
size++;
}
I'm creating a function that removes a node from a linked list but it is giving me a NullPointerException. I tried to check to see if the next one is null but it is giving me that error there now.
Remove function:
private boolean remove(Node aNode)
{
Node prevNode, nextNode;
prevNode = this.getPrevious(aNode);
if(aNode.getNext()==null){ // NullPointerException
return false;
}
else{
nextNode = aNode.getNext();
prevNode.setNext(nextNode);
}
return false;
}
Node class:
public class Node
{
///////////////////////////////////
// Properties //
///////////////////////////////////
private Object myData;
private Node myNext;
///////////////////////////////////
// Methods //
///////////////////////////////////
/**
* Default constructor for a node with null
* data and pointer to a next node
*/
public Node()
{
myData = null;
myNext = null;
}
/**
* Constructor for a node with some object for
* its data and null for a pointer to a next node
*
* <pre>
* pre: a null node
* post: a node with some object for its data and
* null for a pointer to a next node
* </pre>
*
* #param datum an object for the node's data
*/
public Node(Object datum)
{
myData = datum;
myNext = null;
}
/**
* Constructor for a node with some object for
* its data and a pointer to another node
*
* <pre>
* pre: a null node
* post: a node with some object for its data and
* a pointer to a next node
* </pre>
*
* #param datum an object for the node's data
* #param next the node that this node points to
*/
public Node(Object datum, Node next)
{
myData = datum;
myNext = next;
}
// Accessor methods
public void setData(Object datum)
{
myData = datum;
}
public Object getData()
{
return myData;
}
public void setNext(Node next)
{
myNext = next;
}
public Node getNext()
{
return myNext;
}
}
Here is the main section of the full Linked List class
public static void main(String[] args)
{
LinkedList linkedList;
Node testNode1, testNode2, testNode10, foundNode;
boolean success;
linkedList = new LinkedList();
// Test "inList()" method
testNode1 = new Node(new Integer(1));
testNode2 = new Node(new Integer(2));
testNode10 = new Node(new Integer(10));
// System.out.println("In List = "+linkedList.inList(null));
linkedList.printList();
foundNode = linkedList.findNode(new Integer(2));
System.out.println("Found node "+foundNode);
success = linkedList.remove(null);
System.out.println("Success = "+success);
success = linkedList.remove(testNode1);
System.out.println("Success = "+success);
linkedList.addFirst(testNode1);
success = linkedList.remove(testNode1);
System.out.println("Success = "+success);
linkedList.printList();
// System.out.println("In List = "+linkedList.inList(null));
// System.out.println("In List = "+linkedList.inList(testNode1));
// System.out.println("In List = "+linkedList.inList(testNode2));
// Test "addLast()" and "addFirst()" methods
linkedList.addLast(new Node(new Integer(1)));
linkedList.addLast(new Node(new Integer(2)));
linkedList.addLast(new Node(new Integer(3)));
linkedList.addLast(testNode10);
foundNode = linkedList.findNode(new Integer(2));
System.out.println("Found node "+foundNode.toString());
linkedList.printList();
Node testNode;
testNode = linkedList.getPrevious(foundNode);
System.out.println(testNode.getData());
System.exit(0);
success = linkedList.insertBefore("H", testNode1);
System.out.println("Success = "+success);
linkedList.printList();
linkedList.addFirst(new Node(new Integer(1)));
linkedList.addFirst(new Node(new Integer(2)));
linkedList.addFirst(new Node(new Integer(3)));
linkedList.printList();
success = linkedList.insertBefore("A", testNode10);
System.out.println("Success = "+success);
linkedList.printList();
// Test "remove()"
success = linkedList.remove(testNode1);
System.out.println("Success = "+success);
success = linkedList.remove(testNode2);
System.out.println("Success = "+success);
success = linkedList.remove(testNode10);
System.out.println("Success = "+success);
linkedList.printList();
}
}
You get that exception because aNode is null and you try to call a null object's getNext() method, which means at some point, you called remove(null). Since you don't show us where you call remove(), it is impossible to tell, but you either need to make sure that doesn't happen, or check explicitly if aNode is null before attempting to call methods on it.
If you aren't expecting aNode to be null but it is, you should double check your code to make sure you are actually implementing everything properly, as this is a good indication that something is going wrong elsewhere in your algorithm.
Update (looking at your edited question with new code): You have:
success = linkedList.remove(null);
That is the source of your problem; my above answer covers your options for fixing the exception.
In the future you need to examine (and post) the entire stack trace of your exception, which would clearly identify that line of code.
You must be calling remove with aNode set to null. There is no other explanation for this behavior.
It is good practise to assert aNode != null if you do not expect it to be.
It could only mean that aNode itself is null
I have a Neo4j graph database which maps a file system structure consisting of nodes representing folders and files.
Each node has a FATHER_OF and a CHILD_OF relationship.
Now I need to create a TreeNode structure in Java starting from the Neo4j graph: currently I implemented a breadth first print of the NEO4J structure as follows:
public Traverser getTraverser()
{
Transaction tx = graphDb.beginTx();
Traverser traverser = traverseStorage(rootNode);
return traverser;
}
private static Traverser traverseStorage(final Node startNode) {
TraversalDescription td = Traversal.description()
.breadthFirst()
.relationships(GraphStorage.RelTypes.FATHER_OF, Direction.OUTGOING);
return td.traverse(startNode);
}
Now I'm trying to create a Tree using the above breadth-first traverser but can't figure out how to properly assign the correct parent to each node.
TreeNode root = new DefaultTreeNode("root", null);
Traverser traverser = graphStorage.getTraverser();
TreeNode parent = root;
for (Path directoryPath : traverser) {
DefaultTreeNode tmp1 = new DefaultTreeNode((String)directoryPath.endNode().getProperty("name"), parent);
}
I hoped there was something like directoryPath.endNode().getParent() but apparently there isn't.
I'm searching for a solution which doesn't require me to use Cypher query language, any help?
Ok found out, just need a HashMap to map Neo4j node id's to TreeNode objects:
HashMap<Long, TreeNode> treeNodeMap = new HashMap();
then the rest becomes:
TreeNode root = new DefaultTreeNode("root", null);
Traverser traverser = graphStorage.getTraverser();
TreeNode parent = root;
Relationship parentRelationship = directoryPath.endNode().getSingleRelationship(
GraphStorage.RelTypes.CHILD_OF, Direction.OUTGOING);
if (parentRelationship != null) {
Node parentFileNode = parentRelationship.getEndNode();
if (parentFileNode != null) {
long parentId = parentFileNode.getId();
parent = treeNodeMap.get(new Long(parentId));
}
DefaultTreeNode tmp1 = new DefaultTreeNode((String)directoryPath.endNode().getProperty("name"), parent);
treeNodeMap.put(new Long(directoryPath.endNode().getId()), tmp1);
}
The above correctly works.
There is a structure like this:
public class TreeNode {
private String key;
private List<TreeNode> children;
....
}
I override the toString() function
#Override
public String toString() {
String treeStructure = "TreeNode [key=" + key + "]";
if(children!=null){
for(TreeNode child:children){
treeStructure = treeStructure+"--- >"+children.toString()+"/n";
}
}
return treeStructure;
}
Then I test the result:
public static void main(String[] args) {
TreeNode node = new TreeNode();
node.setKey("root");
List<TreeNode> children = new ArrayList<TreeNode>();
TreeNode child1 = new TreeNode();
child1.setKey("child1");
TreeNode child2 = new TreeNode();
child2.setKey("child2");
children.add(child1);
children.add(child2);
List<TreeNode> grandchildren = new ArrayList<TreeNode>();
TreeNode grandchild = new TreeNode();
grandchild.setKey("grandchild");
grandchildren.add(grandchild);
node.setChildren(children);
child1.setChildren(grandchildren);
System.out.println(node);
}
But when I run it the output is:
TreeNode [key=root]--->[TreeNode [key=child1]--->[TreeNode [key=grandchild]]/n, TreeNode [key=child2]]/n--->[TreeNode [key=child1]--->[TreeNode [key=grandchild]]/n, TreeNode [key=child2]]/n
How can I add the newline in the output like this:
TreeNode [key=root]--->TreeNode [key=child1]--->TreeNode [key=grandchild]
--->TreeNode [key=child2]
But now the child1 showed twice and the newline wasn't added in the result.
================================
I changed the function:
#Override
public String toString() {
String treeStructure = "TreeNode [key=" + key + "]";
if(children!=null){
for(TreeNode child:children){
treeStructure = treeStructure+"\n"+"-->"+children.toString()+"\n";
}
}
return treeStructure;
}
then the output is:
TreeNode [key=root]
--->[TreeNode [key=child1]
--->[TreeNode [key=grandchild]]
, TreeNode [key=child2]]
--->[TreeNode [key=child1]
--->[TreeNode [key=grandchild]]
, TreeNode [key=child2]]
why the child repeated twice and where is the "," from?
Use \n instead of /n
treeStructure = treeStructure + "--- >" + children.toString() + "\n";
Don't do it.
Newlines don't belong in toString() methods. They will create quite a mess when someone decides to create a list or map of these objects. toString() should not be a prettyprint. Use a specific method for that purpose so it can have reliable output. toString() has no such contract to produce formatted output.
Try to use \r\n or with BufferedWriter: BufferedWriter.newLine()
The , is written because it is seen like an Array.
The same reason is for child1 repeated.
Change:
treeStructure+"\n"+"-->"+children.toString()+"\n"
to:
treeStructure+"-->"+child.toString()+"\n"
Can i get the full xpath from the org.w3c.dom.Node ?
Say currently node is pointing to some where the middle of the xml document. I would like extract the xpath for that element.
The output xpath I'm looking for is //parent/child1/chiild2/child3/node. A parent to node xpath. Just ignore the xpath's which are having expressions and points to the same node.
There's no generic method for getting the XPath, mainly because there's no one generic XPath that identifies a particular node in the document. In some schemas, nodes will be uniquely identified by an attribute (id and name are probably the most common attributes.) In others, the name of each element (that is, the tag) is enough to uniquely identify a node. In a few (unlikely, but possible) cases, there's no one unique name or attribute that takes you to a specific node, and so you'd need to use cardinality (get the n'th child of the m'th child of...).
EDIT:
In most cases, it's not hard to create a schema-dependent function to assemble an XPath for a given node. For example, suppose you have a document where every node is uniquely identified by an id attribute, and you're not using namespaces. Then (I think) the following pseudo-Java would work to return an XPath based on those attributes. (Warning: I have not tested this.)
String getXPath(Node node)
{
Node parent = node.getParent();
if (parent == null) {
return "/" + node.getTagName();
}
return getXPath(parent) + "/" + "[#id='" + node.getAttribute("id") + "']";
}
I am working for the company behind jOOX, a library that provides many useful extensions to the Java standard DOM API, mimicking the jquery API. With jOOX, you can obtain the XPath of any element like this:
String path = $(element).xpath();
The above path will then be something like this
/document[1]/library[2]/books[3]/book[1]
I've taken this code from
Mikkel Flindt post & modified it so it can work for Attribute Node.
public static String getFullXPath(Node n) {
// abort early
if (null == n)
return null;
// declarations
Node parent = null;
Stack<Node> hierarchy = new Stack<Node>();
StringBuffer buffer = new StringBuffer();
// push element on stack
hierarchy.push(n);
switch (n.getNodeType()) {
case Node.ATTRIBUTE_NODE:
parent = ((Attr) n).getOwnerElement();
break;
case Node.ELEMENT_NODE:
parent = n.getParentNode();
break;
case Node.DOCUMENT_NODE:
parent = n.getParentNode();
break;
default:
throw new IllegalStateException("Unexpected Node type" + n.getNodeType());
}
while (null != parent && parent.getNodeType() != Node.DOCUMENT_NODE) {
// push on stack
hierarchy.push(parent);
// get parent of parent
parent = parent.getParentNode();
}
// construct xpath
Object obj = null;
while (!hierarchy.isEmpty() && null != (obj = hierarchy.pop())) {
Node node = (Node) obj;
boolean handled = false;
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element e = (Element) node;
// is this the root element?
if (buffer.length() == 0) {
// root element - simply append element name
buffer.append(node.getNodeName());
} else {
// child element - append slash and element name
buffer.append("/");
buffer.append(node.getNodeName());
if (node.hasAttributes()) {
// see if the element has a name or id attribute
if (e.hasAttribute("id")) {
// id attribute found - use that
buffer.append("[#id='" + e.getAttribute("id") + "']");
handled = true;
} else if (e.hasAttribute("name")) {
// name attribute found - use that
buffer.append("[#name='" + e.getAttribute("name") + "']");
handled = true;
}
}
if (!handled) {
// no known attribute we could use - get sibling index
int prev_siblings = 1;
Node prev_sibling = node.getPreviousSibling();
while (null != prev_sibling) {
if (prev_sibling.getNodeType() == node.getNodeType()) {
if (prev_sibling.getNodeName().equalsIgnoreCase(
node.getNodeName())) {
prev_siblings++;
}
}
prev_sibling = prev_sibling.getPreviousSibling();
}
buffer.append("[" + prev_siblings + "]");
}
}
} else if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
buffer.append("/#");
buffer.append(node.getNodeName());
}
}
// return buffer
return buffer.toString();
}
For me this one worked best ( using org.w3c.dom elements):
String getXPath(Node node)
{
Node parent = node.getParentNode();
if (parent == null)
{
return "";
}
return getXPath(parent) + "/" + node.getNodeName();
}
Some IDEs specialised in XML will do that for you.
Here are the most well known
oXygen
Stylus Studio
xmlSpy
For instance in oXygen, you can right-click on an element part of an XML document and the contextual menu will have an option 'Copy Xpath'.
There are also a number of Firefox add-ons (such as XPather that will happily do the job for you. For Xpather, you just click on a part of the web page and select in the contextual menu 'show in XPather' and you're done.
But, as Dan has pointed out in his answer, the XPath expression will be of limited use. It will not include predicates for instance. Rather it will look like this.
/root/nodeB[2]/subnodeX[2]
For a document like
<root>
<nodeA>stuff</nodeA>
<nodeB>more stuff</nodeB>
<nodeB cond="thisOne">
<subnodeX>useless stuff</subnodeX>
<subnodeX id="MyCondition">THE STUFF YOU WANT</subnodeX>
<subnodeX>more useless stuff</subnodeX>
</nodeB>
</root>
The tools I listed will not generate
/root/nodeB[#cond='thisOne']/subnodeX[#id='MyCondition']
For instance for an html page, you'll end-up with the pretty useless expression :
/html/body/div[6]/p[3]
And that's to be expected. If they had to generate predicates, how would they know which condition is relevant ? There are zillions of possibilities.
Something like this will give you a simple xpath:
public String getXPath(Node node) {
return getXPath(node, "");
}
public String getXPath(Node node, String xpath) {
if (node == null) {
return "";
}
String elementName = "";
if (node instanceof Element) {
elementName = ((Element) node).getLocalName();
}
Node parent = node.getParentNode();
if (parent == null) {
return xpath;
}
return getXPath(parent, "/" + elementName + xpath);
}