Creating an edge from a node in Java [duplicate] - java

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 3 years ago.
I get an error whenever I try to create a simple edge from a node.
Basically, I've created two of my own classes called Node and Edge.
The Node class is as follows:
public class Node {
public String ident;
public int numLinks;
public Edge[] neighbours;
public Node (String ident) {
this.ident = ident;
}
public void setNeighbour (Node start, Node end, int cost, int portNum) {
}
}
And my Edge class is as follows:
public class Edge {
Node start;
Node end;
int cost;
int portNum;
public Edge (Node a, Node b, int cost, int portNum) {
this.start = a;
this.end = b;
this.cost = cost;
this.portNum = portNum;
}
}
In my main class, I create two nodes, namely, the start and the end node. The cost and the port number (port number that both these nodes listen to on), I read from a text file and am saving them into an array list named "linkCostList" and "portNumList".
Now, since each start node can have more than one edge (I'm basically creating a graph), I'm calling the setNeighbour() method in the following way:
for (int i = 0; i < startNode.numLinks; i++) {
nextNode = new Node (String name of node I read from text file)
startNode.setNeighbour (startNode, nextNode, linkCostList.get(i), portNumList.get(i));
}
My setNeighbour method is as follows:
public void setNeighbour (Node start, Node end, int cost, int portNum) {
for (int i = 0; i < start.numLinks; i++) {
neighbours[i] = new Edge (start, end, cost, portNum);
}
}
Whenever I compile it, I get an error of the following sort:
Exception in thread "main" java.lang.NullPointerException
at Node.setNeighbour(Node.java: *line number*)
at Start.startlsr(Start.java: *line number*)
at graph.main(lsr.java: *line number*)
}
I understand that this is a null pointer exception, so, somewhere in that loop, I must be doing something wrong. Could anyone please help me figure it out?

Have you initialzed neighbours in your Node class? It looks like the exception is from accessing a null array (neighbours[i]).
Also It looks like the neighbours array will grow/shrink dynamically? In this case, instead of using array, consider using ArrayList so you don't have to grow neighbours yourself.

Further to #Alvin's answer (you haven't initialized neighbours nor allowed for expansion), try this:
public List<Edge> neighbours = new ArrayList<Edge>();
Also make use of java's "foreach":
for (Edge edge : start.neighbours) {
// .. some code
}
Consider renaming "neighbours" to "edges", since they are just that - the edges of the node.
Finally, it seems you have a bug in your logic. It seems too complicated. You may be attempting to keep references of neighbours of neighbours. Consider simply looking stuff up when you need it.

Related

Traversing,Insertion and Deletion in LinkedList data structure in java [duplicate]

This question already has answers here:
How to implement a Linked List in Java? [duplicate]
(7 answers)
Closed 6 years ago.
I am new to data structures. I am very curious to learn data structures, but i didnt find any healthy tutorial for that so I am posting it here thinking someone would help me. I know theory of linked list but m totally blank while implementation. If Someone can make me understand how it works that would be really helpful for me.Like, how to traverse through Linked List ,insert and delete. Please provide me a running code so that its easy for me to understand.
I KNOW there are lot of peoples who will think to mark this question as a duplicate and downvote this. Rather than finding mistakes if you guys provide me a good solution that would be really Helpful. Thanks.
Simple implementation of a linked list showing append, insert, delete and iterate. There are inefficiencies, they're for you to figure out :) Go do some research to see how to make it better.
public class LinkedList {
public static class Node {
private Object data;
private Node next = null;
public Node(Object data) {
this.data = data;
}
public void setNext(Node n) {
next = n;
}
public Node getNext() {
return next;
}
public Object getData() {
return data;
}
}
public static void iterate(Node n) {
while (n != null) {
System.out.println(n.getData());
n = n.getNext();
}
}
public static void insert(Node newNode, Node after) {
newNode.setNext(after.getNext());
after.setNext(newNode);
}
public static void delete(Node toDelete, Node root) {
Node n = root;
while (n.getNext() != toDelete) {
n = n.getNext();
}
n.setNext(toDelete.getNext());
}
public static void main(String[] args) {
Node a = new Node("a");
Node b = new Node("b");
Node c = new Node("c");
// append
a.setNext(b);
b.setNext(c);
// iterate
System.out.println("Initial list");
iterate(a);
// insert d after b
Node d = new Node("d");
insert(d, b);
// iterate again
System.out.println("After insert");
iterate(a);
// delete d
delete(d, a);
// iterate again
System.out.println("After delete");
iterate(a);
}
}
Well to start, if you go on youtube and search up Derek Banas you will find a great video just on LinkedLists, and how to implement them. He talks kind of fast, but the content is very well taught in my opinion. Just following along in his videos and after the video I think you will have a better understanding.
https://www.youtube.com/watch?v=195KUinjBpU

A* pathfinding with Multiple Agents

I've currently been learning and programming pathfinding(in Java) using the A* algorithm. A problem I've run into is when multiple entities are trying to pathfind, they both alter the previousNode(the Node that the Node being calculated on came from), messing up the algorithm, and eventually Node A will point to Node B and Node B will point to Node A.
How can I change the algorithm to either
Not use this previousNode system that is littered throughout all of the A * algorithms(that I have seen, that is)
Alter this system to be used concurrently
I am trying to avoid having one entity finish pathfinding, then telling the next entity to pathfinding, and so on. Like doing a wait() - notify() pair in Java.
public Path findPath(int startX, int startY, int goalX, int goalY) {
//Path is basically just a class that contains an ArrayList,
//containing Nodes, which contains the steps to reach a goal.
if(map.getNode(goalX, goalY).isObstacle()) {
return null;
}
map.getNode(startX, startY).setDistanceFromStart(0);
closedList.clear();
openList.clear(); //A List with added getFirst() - gets the first Node in the list
openList.add(map.getNode(startX, startY));
while(openList.size() != 0) {
//Node contains a List that has all of the Nodes around this node, a
//F, G, and H value, and its row(y) and column(x)
Node current = openList.getFirst();
if(current.getX() == goalX && current.getY() == goalY) {
return backtrackPath(current);
}
openList.remove(current);
closedList.add(current);
for(Node neighbor : current.getNeighborList()) {
boolean neighborIsBetter;
//If I've already searched this neighbor/node, don't check it
if(closedList.contains(neighbor)) {
continue;
}
if(!neighbor.isObstacle()) {
float neighborDistanceFromStart = (current.getDistanceFromStart() + map.getDistanceBetween(current, neighbor));
if(!openList.contains(neighbor)) {
openList.add(neighbor);
neighborIsBetter = true;
} else if(neighborDistanceFromStart < current.getDistanceFromStart()) {
neighborIsBetter = true;
} else {
neighborIsBetter = false;
}
if(neighborIsBetter) {
neighbor.setPreviousNode(current);
neighbor.setDistanceFromStart(neighborDistanceFromStart);
neighbor.setHeuristic(getManhattanDistance(neighbor.getX(), neighbor.getY(), goalX, goalY));
}
}
}
}
return null;
}
public Path backtrackPath(Node fromNode) {
Path path = new Path();
while(fromNode.getPreviousNode() != null) {
path.prependWaypoint(fromNode);
fromNode = fromNode.getPreviousNode();
}
return path;
}
I am specifically talking about(within findPath())
if(neighborIsBetter) {
neighbor.setPreviousNode(current); //previousNode is a value in the Node class that points to the Node that it came from
neighbor.setDistanceFromStart(neighborDistanceFromStart);
neighbor.setHeuristic(getManhattanDistance(neighbor.getX(), neighbor.getY(), goalX, goalY));
}
I don't think you can do A* (or any pathfinding algorithm, for that matter) without somehow storing a backpointer for a given path. So that leaves you with two options
Require each agent (Thread, I assume) to create their own copy of the graph to work on. That way each A* call going on won't interfere with one another, as they are working with the fields of the same node on different graphs.
Change your A* code to be able to handle multiple concurrent calls.
Option 1 is fairly self-explanatory and probably the better option. If this is just for you, you should probably just go with that one (instead of trying to make A* fully concurrent on a single graph). This would entail adding map as an input parameter (and requiring that concurrent calls should use a different map instance, either throwing an exception or having unspecified behavior if that doesn't occur). Additionally, you should instantiate closedList and openList as new data structures in each call, rather than share a list.
If that's not to your liking - you really want to fully encapsulate the mutli-call usage into the method itself, I think the simplest way you could do this is require an additional parameter of an id - some unique string that is guaranteed not to be the same as the id of another concurrent call. So the header of A* now looks like:
public Path findPath(final String ID, int startX, int startY, int goalX, int goalY) {
From there, change all of the implementations of each of the settable pathfinding fields in Node to a HashMap with the id as the key. From your code, I'm going to guess that your Node class looks something like this:
public class Node{
//Fields used by the A* call - no problem here
private boolean obstacle;
//Fields *edited* by the A* call
private float distanceFromStart;
private Node previous;
private int heuristic;
//other fields and stuff
public boolean isObstacle(){
return obstacle;
}
public float getDistanceFromStart(){
return distanceFromStart;
}
public void setDistanceFromStart(float f){
distanceFromStart = f;
}
public Node getPrevious(){
return previous;
}
public void setPrevious(Node p){
previous = p;
}
public int getHeuristic(){
return heuristic;
}
public void setHeuristic(int h){
heuristic = h;
}
}
We can edit the edited fields to be able to store many values, by id, as such:
public class Node{
//Fields used by the A* call - no problem here
private boolean obstacle;
//Fields *edited* by the A* call
private HashMap<String,Float> distanceFromStart;
private HashMap<String,Node> previous;
private HashMap<String,Integer> heuristic;
//other fields and stuff
public boolean isObstacle(){
return obstacle;
}
public float getDistanceFromStart(String id){
return distanceFromStart.get(id);
}
public void setDistanceFromStart(String id, float f){
distanceFromStart.put(id, f);
}
public Node getPrevious(String id){
return previous.get(id);
}
public void setPrevious(String id, Node p){
previous.put(id,p);
}
public int getHeuristic(String id){
return heuristic.get(id);
}
public void setHeuristic(String id,int h){
heuristic.put(id,h);
}
}
From there, simply edit your A* method to give the id from the method call to the getters and setters when called for. So long as two concurrent method calls don't have the same id value, they won't interfere with each other. Three things to keep in mind for this to work correctly:
Make sure that every editable field gets this treatment. It won't work if you forget about one. Non-editable fields (fields that don't get altered as a byproduct of running A*) can stay singular.
If you use the the above, you should probably add to the cleanup stage a step of removing all the information for the given ID from the graph, or the nodes' hashmaps will grow larger with each call.
Either way, you still should make openList and closedList new local instances, no matter what concurrent approach you pick. There's nothing to gain from making openList and closedList shared instances, and only bugs can come of it.
List<Node> closedList = new LinkedList<Node>();
List<Node> openList = new LinkedList<Node>();
//Don't have to clear them anymore - they're new lists
openList.add(map.getNode(startX, startY));

Creating a linked list of notes from a Phrase (Jmusic)

I have this constructor that takes in a phrase of jmusic notes, and I'm trying to set each individual note to an individual node in a linked list of SoloNodes which hold one individual note only. most of the methods in that constructor I've written myself but they're pretty self explanatory. What exactly must I do to make this generate a linked list?
public Solo(Phrase myPhrase)
{
int length=myPhrase.length();
head=new SoloNode();
SoloNode next=new SoloNode();
for(int i=1; i<=length;i++)
{
head.setNote(myPhrase.getNote(i));
next=head.copyNode();
head.setNext(next);
head=next;
i++;
}
}
I guess that's the code you are looking for:
private SoloNode head;
public Solo(Phrase myPhrase)
{
int length = myPhrase.length();
SoloNode node = new SoloNode();
head = node;
for (int i = 0; i < length; i++) {
node.setNote(myPhrase.getNote(i));
if (i + 1 < length) {
node.setNext(new SoloNode());
node = node.getNext();
}
}
}
I assumed you are using a class SoloNode which looks like this.
I assumed too that myPhrase.getNote(i) starts with index 0 (not 1) because that is the common way how it works in Java.
After you run this code the SoloNodes are filled with data from myPhrase and linked from one to next. With getNext() you can navigate from current to next. Only for last SoloNode it will return null.

change values of array of a class in java

I am writting a program that performs an a star search throughout a map. I have created a class that hold all the nodes of the map.
public Node {
Node up_node, right_node, down_node, left_node;
}
public class Star {
public static void main(String args[]) {
Node a=new Node();
Node b=new Node();
Node h=new Node();
Node here=new Node();
Node[] NextNode;
NextNode = new Node[10];
for(int i=0;i<10;i++) {
NextNode[i]=new Node();
}
int j=0;
a.up_node=h;
a.right_node=b;
b.left_node=a;
h.down_node=a;
//if certain conditions are met
NextNode[j].here_node=a.up_node;
//what i was hoping to do is copy the node a.up which is h
}
}
into NextNode[0] in this case. However it keeps returning a memory address of some sort : test.Node#10b28f30: test being the name of the package, please help!
#override the toString() method to display the internal property of your class.
By default, java display the full class name#hashCode value.
Variables in Java are object references not actual objects. NextNode[j].here_node = a.up_node; will make NextNode[j].here_node and a.up_node point to the same object. Is this not what you want?
If you wanted to make a completely new copy of the object, then you can implement that in the Node class:
public class Node {
Node up_node, right_node, down_node, left_node;
public Node clone() {
Node ret = new Node();
// copy the properties
ret.up_node = this.up_node;
...
return ret;
}
}
Now
NextNode[j].here_node = a.up_node.clone();
will make a copy (although it's only a shallow one -- the copy will point to the same objects via its fields as opposed to copies of them).
I assume your confusion about the code returning "an address" comes because you tried to print a node, e.g.
System.out.println(a.up_node);
You'll get something like test.Node#10b28f30, but try
System.out.println(NextNode[j].here_node);
and you should get exactly the same string, indicating that they're pointing to the same object.
To get something nicer, you must override Node's implementation of toString(). Here's an example that will give each Node a unique number:
public class Node {
Node up_node, right_node, down_node, left_node;
// how many nodes were created
private static int count = 0;
// the number of this node
private int number;
public Node() {
// increment the number of nodes created
++Node.count;
// assign that number to this node
this.number = Node.count;
}
public String toString() {
return "Node #" + this.number;
}
}
We know that every class that we write are child of Object class. When we print a child of an Object it prints its toString() method. By default it is a hashed value of memory location. So it prints sort weird things. if we #overriding toString method to return something more meaningful to us then we can solve this problem. If we can name our node class someway I think we can keep track of them easily
class Node(){
String nameOfNode;
//contractor to keep track of where it goes.
public Node(String a){
nameOfNode=a;
}
//when we will print a Node it is going to print its name
public String toString(){
return nameOfNode;
}
}
Then it will print the name of the node. And it will stop showing that weird memory address.
and replace your new Node() with distinct name new Node("a name")

Iterators over Tries in Java

I am currently trying to implement a trie data structure for integer tuples. And have implemented as follows:
import java.util.ArrayList;
public class TrieNode {
int num;
ArrayList<TrieNode> links;
boolean endOfTuple;
public TrieNode(int num)
{
this.num = num;
links = new ArrayList<TrieNode>();
this.endOfTuple = false;
}
}
I then have a trie class as follows:
public class Trie {
TrieNode root;
public Trie() {
root = new TrieNode(-1);
}
public void insertTuple(int[] tuple)
{
int l = tuple.length;
TrieNode curNode = root;
for (int i = 0; i < l; i++)
{
TrieNode node = new TrieNode(tuple[i]);
if(!curNode.links.contains(node)){
curNode.links.add(node);
}
curNode = curNode.links.get(curNode.links.indexOf(node));
}
curNode.endOfTuple = true;
}
}
I can add values to this trie, but i need to be able to iterate over this and was wondering how i could do this? For example if i wanted to print the tree using an iterator...Any help will be great...
All you need for an interator is to implement the Iterator interface, which only requires that you supply boolean hasNext() and Integer next(). So the question to ask is: how do represent a position in your trie, such that it's possible to (a) fetch the value associated with that position, and (b) figure out the "next" position given a current one?
I'll refrain from posting an actual solution since I'm not sure whether this is homework. But consider: you can represent a "current position" in your trie just by choosing a particular trie node, and the path of trie nodes you used to reach it. Then you can compute the "next" element recursively: if the current element is a node that has children, then find the first child for which endOfTuple is true. If the current element doesn't have children, then go to its parent and advance to that parent's next child. If that parent doesn't have next children, then go it its parent's next child, etc.

Categories

Resources