[JAVA} A-Star code isn't finding optimal Path - java

I'm trying to code A* search algorithm but I can't seem to get it to work. I'm copying the pseudocode from wikipedia. My code seems to just search every possible node. Here's my showPath() function:
public void showPath() {
Nodes current = end;
while(current.cameFrom!=null) {
current.isPath = true;
current = current.cameFrom;
}
}
The start node will have a cameFrom of null since that's it's default value.
public void A_Star() {
PriorityQueue<Nodes> closedSet = new PriorityQueue<Nodes>();
PriorityQueue<Nodes> openSet = new PriorityQueue<Nodes>();
closedSet.clear();
openSet.clear();
start.gScore = 0;
openSet.add(start);
start.fScore = getDist(start,end);
while(!(openSet.size() ==0)) {
Nodes curr = openSet.poll();
if(curr.x == end.x && curr.y == end.y) {
showPath();
}
closedSet.add(curr);
for(int i=0;i<curr.getNeighbourCount();i++) {
Nodes neighbour = curr.getNeighbour(i);
if(closedSet.contains(neighbour)) {
continue;
}
//isPassable is a boolean that is false if the Nodes is an obstacle
if(!openSet.contains(neighbour) && neighbour.isPassable) {
openSet.add(neighbour);
}
//It's a grid so every point is a distance of 1 from it's neighbours
else if((curr.gScore+1)>= neighbour.gScore){
continue;
}
neighbour.cameFrom = curr;
neighbour.gScore = curr.gScore+1;
neighbour.fScore = neighbour.gScore + getDist(neighbour,end);
}
}
}
EDIT: My getDist function
public int getDist(Nodes node1, Nodes node2) {
return ( Math.abs(node1.x - node2.x) + Math.abs(node1.y - node2.y));
}

If you look at this picure, you have to notice that, with Manhatten distance, all of the paths from start to the goal has equal distances. This will cause that, you will visit all.
Change your distance to Euclidean Distance.

Related

How to perform different basic traversals of graphs?

I am trying to perform an iterative breadth first traversal, iterative depth first traversal, and recursive depth first traversal of a given graph (using an adjacency matrix).
In its current state, my program outputs various wrong answers.
Here's some examples.
I am expecting
From Node A
DFS (iterative): A B H C D E I F G
DFS (recursive): A B H C D E I F G
BFS (iterative): A B D I H C E F G
but am instead getting
From Node A
DFS (iterative): A I D B H C F G E
DFS (recursive): A B H C F D E I G
BFS (iterative): A B D I H C E F G
I'm unsure if the problem with my program lies within the implementation of the traversals, or my implementation of some other part of the program. To be more specific, I'm not sure if my implementation connectNode or getNeighbors method is what is causing the incorrect output, or if it is my implementation of the traversals.
EDIT: Neighbors are supposed to be chosen in ascending order, if that's important. Perhaps this is part of the problem?
EDIT2: I added the new line of code, thanks to #HylianPikachu's suggestion. I now get full answers, but they are still not in the correct order.
EDIT3: I added the code to make it so the root node is checked as visited for bfs and recursive dfs. I think. I should also note that I was given parts of this code and told to fill in the rest. The use of the stack and queue are what I was told to use, even though there might be better options.
EDIT4: Added what was suggested, and now, the Iterative BFS works and gets the correct result. However, both DSF searches still do not work. I modified the results of the program above, to show this.
import java.util.*;
public class GraphM {
public Node rootNode;
public List<Node> nodes = new ArrayList<Node>(); // nodes in graph
public int[][] adjMatrix; // adjacency Matrix
public void setRootNode(Node n) {
rootNode = n;
}
public Node getRootNode() {
return rootNode;
}
public void addNode(Node n) {
nodes.add(n);
}
// This method connects two nodes
public void connectNode(Node src, Node dst) {
if(adjMatrix == null) {
adjMatrix = new int[nodes.size()][nodes.size()];
}
adjMatrix[nodes.indexOf(src)][nodes.indexOf(dst)] = 1;
adjMatrix[nodes.indexOf(dst)][nodes.indexOf(src)] = 1;
}
// Helper method to get one unvisited node from a given node n.
private Node getUnvisitedChildNode(Node n) {
int index = nodes.indexOf(n);
int size = adjMatrix.length;
for (int j = 0; j < size; j++)
if (adjMatrix[index][j] == 1 && ((Node) nodes.get(j)).visited == false)
return nodes.get(j);
return null;
}
// get all neighboring nodes of node n.
public List<Node> getNeighbors(Node n) {
List<Node> neighbors = new ArrayList<Node>();
for(int i = 0; i < nodes.size(); i ++) {
if (adjMatrix[nodes.indexOf(n)][i] == 1) {
neighbors.add(nodes.get(i));
}
Collections.sort(neighbors);
}
return neighbors;
}
// Helper methods for clearing visited property of node
private void reset() {
for (Node n : nodes)
n.visited = false;
}
// Helper methods for printing the node label
private void printNode(Node n) {
System.out.print(n.label + " ");
}
// BFS traversal (iterative version)
public void bfs() {
Queue<Node> queue = new LinkedList<Node>();
queue.add(rootNode);
while(!queue.isEmpty()) {
Node node = queue.poll();
printNode(node);
node.visited = true;
List<Node> neighbors = getNeighbors(node);
for ( int i = 0; i < neighbors.size(); i ++) {
Node n = neighbors.get(i);
if (n != null && n.visited != true) {
queue.add(n);
n.visited = true;
}
}
}
}
// DFS traversal (iterative version)
public void dfs() {
Stack<Node> stack = new Stack<Node>();
stack.add(rootNode);
while(!stack.isEmpty()){
Node node = stack.pop();
if(node.visited != true) {
printNode(node);
node.visited = true;
}
List<Node> neighbors = getNeighbors(node);
for (int i = 0; i < neighbors.size(); i++) {
Node n = neighbors.get(i);
if(n != null && n.visited != true) {
stack.add(n);
}
}
}
}
// DFS traversal (recursive version)
public void dfs(Node n) {
printNode(n);
n.visited = true;
List<Node> neighbors = getNeighbors(n);
for (int i = 0; i < neighbors.size(); i ++) {
Node node = neighbors.get(i);
if(node != null && node.visited != true) {
dfs(node);
}
}
}
// A simple Node class
static class Node implements Comparable<Node> {
public char label;
public boolean visited = false;
public Node(char label) {
this.label = label;
}
public int compareTo(Node node) {
return Character.compare(this.label, node.label);
}
}
// Test everything
public static void main(String[] args) {
Node n0 = new Node('A');
Node n1 = new Node('B');
Node n2 = new Node('C');
Node n3 = new Node('D');
Node n4 = new Node('E');
Node n5 = new Node('F');
Node n6 = new Node('G');
Node n7 = new Node('H');
Node n8 = new Node('I');
// Create the graph (by adding nodes and edges between nodes)
GraphM g = new GraphM();
g.addNode(n0);
g.addNode(n1);
g.addNode(n2);
g.addNode(n3);
g.addNode(n4);
g.addNode(n5);
g.addNode(n6);
g.addNode(n7);
g.addNode(n8);
g.connectNode(n0, n1);
g.connectNode(n0, n3);
g.connectNode(n0, n8);
g.connectNode(n1, n7);
g.connectNode(n2, n7);
g.connectNode(n2, n3);
g.connectNode(n3, n4);
g.connectNode(n4, n8);
g.connectNode(n5, n6);
g.connectNode(n5, n2);
// Perform the DFS and BFS traversal of the graph
for (Node n : g.nodes) {
g.setRootNode(n);
System.out.print("From node ");
g.printNode(n);
System.out.print("\nDFS (iterative): ");
g.dfs();
g.reset();
System.out.print("\nDFS (recursive): ");
g.dfs(g.getRootNode());
g.reset();
System.out.print("\nBFS (iterative): ");
g.bfs();
g.reset();
System.out.println("\n");
}
}
}
So, we already covered the first part of your question, but I'll restate it here for those who follow. Whenever working with graphs and an adjacency matrix, probably the best way to initialize elements in the array is "both ways."
Instead of just using the following, which would require a specific vertex be listed first in order to find the neighbors:
adjMatrix[nodes.indexOf(src)][nodes.indexOf(dst)] = 1;
Use this, which leads to searches that are agnostic of the vertex order:
adjMatrix[nodes.indexOf(src)][nodes.indexOf(dst)] = 1;
adjMatrix[nodes.indexOf(dst)][nodes.indexOf(src)] = 1;
Now, for ordering. You want the vertices to be outputted in order from "least" letter to "greatest" letter. We'll address each one of your data structures individually.
In BFS (iterative), you use a Queue. Queues are "first in, first out." In other words, the element that was least recently added to the Queue will be outputted first whenever you call queue.poll(). Thus, you need to add your nodes from least to greatest.
In DFS (iterative), you use a Stack. Stacks are "last in, first out." In other words, the element that was most recently added to the Stack will be outputted first whenever you call stack.pop(). Thus, you need to add your nodes from greatest to least.
In DFS (recursive), you use a List. Lists have no "in-out" ordering per se, as we can poll them in whatever order we want, but the easiest thing to do would just be to sort the List from least to greatest and output them in order.
With this in mind, we need to introduce protocol for sorting the graph. All three protocols use getNeighbors(), so we'll sort the outputted List immediately after we call that function. Lists can be ordered with the function Collections.sort(List l) from java.utils.Collections, but we first need to modify your nodes class so Java knows how to sort the Nodes. For further reading about the details of what I'm doing, you can look here, but this post is getting way longer than I intended already, so I'm going to just show the code here and let the interested explore the link themselves.
You would first tweak your Node class by implementing Comparable<Node> and adding the compareTo() function.
static class Node implements Comparable<Node>{
public char label;
public boolean visited = false;
public Node(char label) {
this.label = label;
}
#Override
public int compareTo(Node that) {
return Character.compare(this.label, that.label);
}
}
Then, in the cases in which we want to order the List from least to greatest, we can use Collections.sort(neighbors). When we want it from greatest to least, we can use Collections.sort(neighbors, Collections.reverseOrder()). Our final code will look like this:
// BFS traversal (iterative version)
public void bfs() {
Queue<Node> queue = new LinkedList<Node>();
queue.add(rootNode);
while(!queue.isEmpty()) {
Node node = queue.poll();
printNode(node);
node.visited = true;
List<Node> neighbors = getNeighbors(node);
//NEW CODE: Sort our neighbors List!
Collections.sort(neighbors);
for ( int i = 0; i < neighbors.size(); i ++) {
Node n = neighbors.get(i);
if (n != null && n.visited != true) {
queue.add(n);
n.visited = true;
}
}
}
}
// DFS traversal (iterative version)
public void dfs() {
Stack<Node> stack = new Stack<Node>();
stack.add(rootNode);
while(!stack.isEmpty()){
Node node = stack.pop();
if(node.visited != true) {
printNode(node);
node.visited = true;
}
List<Node> neighbors = getNeighbors(node);
//NEW CODE: Sort our neighbors List in reverse order!
Collections.sort(neighbors, Collections.reverseOrder());
for (int i = 0; i < neighbors.size(); i++) {
Node n = neighbors.get(i);
if(n != null && n.visited != true) {
stack.add(n);
}
}
}
}
// DFS traversal (recursive version)
public void dfs(Node n) {
printNode(n);
n.visited = true;
List<Node> neighbors = getNeighbors(n);
//NEW CODE: Sort our neighbors List!
Collections.sort(neighbors);
for (int i = 0; i < neighbors.size(); i ++) {
Node node = neighbors.get(i);
if(node != null && node.visited != true) {
dfs(node);
}
}
}
I would suggest splitting up your problem into smaller parts.
If you want to write a class for an undirected graph, first do that and test it a bit.
If you want to look if you can implement traversal, make sure your graph works first. You can also use guava, which lets you use MutableGraph (and lots more). Here is how to install it in case you're using IntelliJ and here is how to use graphs from guava.
Also remember to use a debugger to find out were your code goes wrong.

How to represent a unweight directed graph and find the shortest path? Java

What is the best way to represent graph in Java ? I did it in this way:
public class Node<T> {
public T data;
public LinkedList<Node> children;
public Node(T data) {
this.data = data;
this.children = new LinkedList<Node>(); //here there are the connected nodes of the node
}
public T getData() {
return this.data;
}
public void addArch(Node n) {
children.add(n);
}
public class Graph <T> {
private Node<T> source = new Node(null);
private Node<T> target = new Node(null);
private ArrayList<Node> nodes = new ArrayList<Node>();
public Graph() {}
public void addNode(T v) {
boolean visto = false;
for (Node n: nodes) {
if (n.getData().equals(v)) {
visto = true;
}
}
if (visto == false) {
nodes.add(new Node(v));
}
}
public void addEdge(T p, T a) throws NoSuchNodeException {
boolean visto = false;
boolean visto_secondo = false;
for (Node n: nodes) {
if (n.getData().equals(p)) {
visto = true;
}
}
for (Node n: nodes) {
if (n.getData().equals(a)) {
visto_secondo = true;
}
}
if (visto == false || visto_secondo == false) {
throw new NoSuchNodeException();
}
else {
for (Node n : nodes) {
if (p.equals(n.getData())) {
System.out.print(a);
n.addArch(new Node(a));
}
}
}
}
I have to find the shortest path but it seems like the archs are not added,why ? I did also the set and get of source and target. However I have to find the shortest path between this source and target,what is the algorithm to use? I need to use a bfs to get the shortest path but my problem is how to iterate over archs,I need to do a recursive function I think
The best algorithm for finding the shortest path to a goal node is Iterative Deepening A*.
It finds the shortest path to the goal node provided the heuristic value is admissible, meaning it doesn't overestimate.
Here is the pseudocode:
node current node
g the cost to reach current node
f estimated cost of the cheapest path (root..node..goal)
h(node) estimated cost of the cheapest path (node..goal)
cost(node, succ) step cost function
is_goal(node) goal test
successors(node) node expanding function, expand nodes ordered by g + h(node)
procedure ida_star(root)
bound := h(root)
loop
t := search(root, 0, bound)
if t = FOUND then return bound
if t = ∞ then return NOT_FOUND
bound := t
end loop
end procedure
function search(node, g, bound)
f := g + h(node)
if f > bound then return f
if is_goal(node) then return FOUND
min := ∞
for succ in successors(node) do
t := search(succ, g + cost(node, succ), bound)
if t = FOUND then return FOUND
if t < min then min := t
end for
return min
end function
The g represents the number of moves to get to the current state and h represents the estimated number of moves to get to the goal state. f := g + h(node). The closer the heuristic value is to the actual number of moves, the faster the algorithm

Trying to print top view of a tree using two if statements

Problem Statement
You are given a pointer to the root of a binary tree. Print the top view of the binary tree.
You only have to complete the function.
My Code:
void top_view(Node root)
{
Node r = root;
if(r.left!=null){
top_view(r.left);
System.out.print(r.data + " ");
}
if(r.right!=null){
System.out.print(r.data + " ");
top_view(r.right);
}
}
The two if statements are executed every time the function is called, but I need only one of them to execute. I tried switch but its giving constant expression error. I have already found a different solution for this problem.
So I only want to know if we can make only one if execute at a time i.e, is there a way to fix my code without changing the approach?
Problem link: https://www.hackerrank.com/challenges/tree-top-view
Your approach will work not because, when you call left or right subtree you will just stick to it. The problem with this approach is you are just driven by which side of the tree is called first.
May be you can solve it by using stack and queue as somebody else said but i feel that the following is a simpler and more intuitive approach:
(SEE THE CODE AT THE END, IT'S VERY SIMPLE)
The approach to solve this is by maintaining horizontal distance from root and you print the first node for each different horizontal distance.
What is horizontal distance?
I am just taking the image you have added.
Horizontal distance for a particular node is defined as the number of from root horizontally. If you see no.of edges that will become vertical distance.
To make things easier for all the nodes on left side of root start with negative horizontal distance and right side positive distance.
How do you calculate horizontal distance?
If you are going right add 1, if you are going left add -1.
so
horizontal distance of 3 = 0
horizontal distance of 5 = -1
horizontal distance of 1 = -2
horizontal distance of 9 = -1
horizontal distance of 4 = 0
horizontal distance of 2 = 1
horizontal distance of 6 = 0
horizontal distance of 7 = 2
horizontal distance of 8 = 1
Nodes 3,4,6 have same horizontal distance of 0 what does the mean?
That means when you see from top all these nodes are in a line vertically one above it.
If they are in a line vertically which one do you see?
The one which is can be reached first from root.
How do you find which one can be reached first?
as usual BFS
How this prints solution for your example?
There are five different horizontal distance value {-1,-2,0,1,2}
hor dist Nodes
0 - {3,6,8} // 3 comes first in BFS so print 3
-1 - {5,9} // 5 comes first in BFS so print 5
-2 - {1} // just print 1
1 - {2} // just print 2
2 - {7} // just print 7
So it will print {3,5,1,2,7}
HashSet<Integer> set = new HashSet<>();
Queue<QueueItem> queue = new LinkedList<>();
queue.add(new QueueItem(root, 0)); // Horizontal distance of root is 0
while (!queue.isEmpty())
{
QueueItem temp = queue.poll();
int hd = temp.hd;
TreeNode n = temp.node;
// If this is the first node at its horizontal distance,
// then this node is in top view
if (!set.contains(hd))
{
set.add(hd);
System.out.print(n.key + " ");
}
if (n.left != null)
queue.add(new QueueItem(n.left, hd-1));
if (n.right != null)
queue.add(new QueueItem(n.right, hd+1));
}
The solution is pretty easy if you print the left side by recursion and the right side using a simple while loop..
void for_left(node *root)
{
if(!root->left)
{
cout<<root->data<<" ";
return;
}
for_left(root->left);
cout<<root->data<<" ";
return;
}
void top_view(node * root)
{
for_left(root->left);
cout<<root->data<<" ";
while(root->right)
{
cout<<(root->right)->data<<" ";
root=root->right;
}
}
This problem can be very easily solved by using:
Stack: To print the root and the left subtree.
Queue: To print the right subtree.
Your function should be like this:
void topview(Node root)
{
if(root==null)
return;
Stack<Integer> s=new Stack<Integer>();
s.push(root.data);
Node root2=root;
while(root.left!=null)
{
s.push(root.left.data);
root=root.left;
}
while(s.size()!=0)
System.out.print(s.pop()+" ");
Queue<Integer> q=new LinkedList<Integer>();
q.add(root2.right.data);
root2=root2.right;
while(root2.right!=null)
{
q.add(root2.right.data);
root2=root2.right;
}
while(q.size()!=0)
System.out.print(q.poll()+" ");
}
This one actually works. Doesn't need a queue, but uses a stack in order to backtrack from the left side, since we don't have reference to the parent.
void top_view(Node root)
{
Stack<Node> p = new Stack<Node>();
Node current = root;
while (current != null)
{
p.push(current);
current = current.left;
}
while (p.peek() != root)
{
System.out.print(p.pop().data + " ");
}
current = root;
while (current != null)
{
System.out.print(current.data + " ");
current = current.right;
}
}
The solution can be found here - Git hub URL
Note that whatever the hackerrank question is with respect to balanced tree, if the tree is in the imbalanced state like below
1
/ \
2 3
\
4
\
5
\
6
For these kind of trees some complicated logic is required which is defined in geeksforgeeks here - GeeksforGeeks
My Java implementation is attached. The left side of the tree is more interesting if solved recursively, but reversing the string(my way below) was easier and only required the use of one method.
public void top_view(Node root){
String output = "";
Node left = root.left;
Node right = root.right;
String leftOutput = "";
while(left != null){
leftOutput += left.data + " ";
left = left.left;
}
String left = "";
for(int i = leftOutput.length - 1; i >= 0; i--){
left += leftOutput.substring(i, i+1);
}
output += left;
output += " " + root.data + " ";
while(right != null){
output += right.data + " ";
right = right.right;
}
output = output.substring(1, output.length());
System.out.println(output);
}
void top_view(Node root)
{
if(root.left!=null) top_view(root.left);
if(root.left!=null || root.right!=null)
System.out.print(root.data + " ");
if(root.right!=null) top_view(root.right);
}
A simpler approach in C++
`// printing top view of the tree
void left_array(node *p)
{
if(p==NULL)
return;
else
{
left_array(p->left);
cout<<p->data<<" ";
}
}
void right_array(node *p)
{
if(p==NULL)
return;
else
{
cout<<p->data<<" ";
right_array(p->right);
}
}
void top_view(node * root)
{ int i=0;
node *t1=root;
node *t2=root;
left_array(t2);
right_array(t1->right);
}`
A very simple recursive solution which takes care of long branches of the child node. This is solved using horizontal distance concept.
public void printTopView(BNode root) {
Map<Integer, Integer> data = new TreeMap<Integer, Integer>();
printTopViewRecursive(data, root, 0);
for(int key : data.keySet()) {
System.out.print(data.get(key) +" ");
}
}
private void printTopViewRecursive(Map<Integer, Integer> hDMap, BNode root, int hD) {
if(root == null)
return;
if(!hDMap.containsKey(hD)) {
hDMap.put(hD, root.data);
}
printTopViewRecursive(hDMap, root.left,hD - 1);
printTopViewRecursive(hDMap, root.right, hD + 1);
}
in java recursivish solution. converted from c++ code
void top_view(Node root)
{
left_array(root);
right_array(root.right);
}
void left_array(Node p)
{
if(p==null)
return;
else
{
left_array(p.left);
System.out.printf("%d ",p.data);
}
}
void right_array(Node p)
{
if(p==null)
return;
else
{
System.out.printf("%d ",p.data);
right_array(p.right);
}
}
void top_view(Node root)
{
Node left = root;
Node right = root;
print_left(root.left);
System.out.print(root.data + " ");
print_right(root.right) ;
}
void print_left(Node start)
{
if(start != null)
{
print_left(start.left);
System.out.print(start.data + " ");
}
}
void print_right(Node start)
{
if(start != null)
{
System.out.print(start.data + " ");
print_right(start.right);
}
}
One simple recursive way to do it:
void top_view(Node root)
{
print_top_view(root.left, "left");
System.out.print(root.data + " ");
print_top_view(root.right, "right");
}
void print_top_view(Node root, String side) {
if(side.equals("left")) {
if(root.left != null) {
print_top_view(root.left, "left");
}
System.out.print(root.data + " ");
} else if(side.equals("right")) {
System.out.print(root.data + " ");
if(root.right != null) {
print_top_view(root.right, "right");
}
}
}
if(root){
if(root->left !=NULL || root->right !=NULL){
if(root->left)
top_view(root->left);
cout<<root->data<<" ";
if(root->right)
top_view(root->right);
}}
This is the code for top-view of a binary tree in c++..
void topview(node* root,queue &Q)
{
if(!root)
return;
map<int,int> TV;
Q.push(root);
TV[root->data]=0;
map<int,int>:: iterator it;
int min=INT_MAX,max=INT_MIN;
while(!Q.empty())
{
node* temp =Q.front();
Q.pop();
int l=0;
for(it=TV.begin();it!=TV.end();it++)
{
if(it->first==temp->data)
{
l=it->second;
break;
}
}
if(l<min)
{min=l;}
if(l>max)
max=l;
if(temp->left)
{
Q.push(temp->left);
TV[temp->left->data] = l-1;
}
if(temp->right)
{
Q.push(temp->right);
TV[temp->right->data] = l+1;
}
}
cout<<max<<min<<endl;
for(int i =min;i<=max;i++)
{
for(it=TV.begin();it!=TV.end();it++)
{
if(it->second==i)
{
cout<<it->first;
break;
}
}
}
}
void topview_aux(node* root)
{
queue<node*> Q;
topview(root,Q);
}
A quite similar approach to the one #Karthik mentioned but with keeping the order, is to postpone the printing to the end and keep top view nodes ordered in double ended queue.
We guarantee the order using BFS
Each round we check if the current node's horizontal distance is larger than the maximum distance reached in the previous rounds (negative distance for left nodes).
New top view nodes with -ve distance (left position) added to the left end of the deque , while right nodes with +ve distance added to the right end.
Sample solution in Java
import java.util.*;
class Node {
int data;
Node left;
Node right;
public Node(int data) {
this.data = data;
}
}
enum Position {
ROOT,
RIGHT,
LEFT
}
class NodePositionDetails {
Node node;
// Node position in the tree
Position pos;
// horizontal distance from the root (-ve for left nodes)
int hd;
public NodePositionDetails(Node node, Position pos, int hd) {
this.node = node;
this.pos = pos;
this.hd = hd;
}
}
public class TreeTopView {
public void topView(Node root) {
// max horizontal distance reached in the right direction uptill the current round
int reachedRightHD = 0;
// max horizontal distance reached in the left direction uptill the current round
int reachedLeftHD = 0;
if (root == null)
return;
// queue for saving nodes for BFS
Queue < NodePositionDetails > nodes = new LinkedList < > ();
// Double ended queue to save the top view nodes in order
Deque < Integer > topViewElements = new ArrayDeque < Integer > ();
// adding root node to BFS queue
NodePositionDetails rootNode = new NodePositionDetails(root, Position.ROOT, 0);
nodes.add(rootNode);
while (!nodes.isEmpty()) {
NodePositionDetails node = nodes.remove();
// in the first round, Root node is added, later rounds left and right nodes handled in order depending on BFS. if the current horizontal distance is larger than the last largest horizontal distance (saved in reachedLeftHD and reachedRightHD)
if (node.pos.equals(Position.LEFT) && node.hd == reachedLeftHD - 1) {
topViewElements.addFirst(node.node.data);
reachedLeftHD -= 1;
} else if (node.pos.equals(Position.RIGHT) && node.hd == reachedRightHD + 1) {
topViewElements.addLast(node.node.data);
reachedRightHD += 1;
} else if (node.pos.equals(Position.ROOT)) { // reachedLeftHD == 0 && reachedRightHD ==0
topViewElements.addFirst(node.node.data);
}
// Normal BFS, adding left and right nodes to the queue
if (node.node.left != null) {
nodes.add(new NodePositionDetails(node.node.left, Position.LEFT, node.hd - 1));
}
if (node.node.right != null) {
nodes.add(new NodePositionDetails(node.node.right, Position.RIGHT, node.hd + 1));
}
}
// print top elements view
for (Integer x: topViewElements) {
System.out.print(x + " ");
}
}
}
And for testing:
public static void main(String[] args) throws java.lang.Exception {
/**
Test Case 1 & 2
1
/ \
2 3
/ \
7 4
/ \
8 5
\
6
Test Case 3: add long left branch under 3 (branch : left to the 3 3-> 8 -> 9 -> 10 -> 11
**/
Node root = new Node(1); //hd = 0
// test Case 1 -- output: 2 1 3 6
root.left = new Node(2); // hd = -1
root.right = new Node(3); // hd = +1
root.left.right = new Node(4); // hd = 0
root.left.right.right = new Node(5); // hd = +1
root.left.right.right.right = new Node(6); // hd = +2
// test case 2 -- output: 8 7 2 1 3 6
root.left.left = new Node(7); // hd = -2
root.left.left.left = new Node(8); // hd = -3
// test case 3 -- output: 11 7 2 1 3 6
root.left.left.left = null;
root.right.left = new Node(8); //hd = 0
root.right.left.left = new Node(9); // hd = -1
root.right.left.left.left = new Node(10); // hd = -2
root.right.left.left.left.left = new Node(11); //hd = -3
new TreeTopView().topView(root);
}
Simplest Recursive Solution
void top_view(Node root)
{
// For left side of the tree
top_view_left(root);
// For Right side of the tree
top_view_right(root.right);
}
void top_view_left(Node root){
if(root != null)
{
// Postorder
top_view_left(root.left);
System.out.print(root.data + " ");
}
}
void top_view_right(Node root){
if(root != null)
{
// Preorder
System.out.print(root.data + " ");
top_view_right(root.right);
}
}
This:
import queue
class NodeWrap:
def __init__(self, node, hd):
self.node = node
#horizontal distance
self.hd = hd
def topView(root):
d = {}
q = queue.Queue()
q.put(NodeWrap(root, 0))
while not q.empty():
node_wrap = q.get()
node = node_wrap.node
current_hd = node_wrap.hd
if d.get(current_hd) is None:
d[current_hd] = node
print(node.info, end=" ")
if node.left is not None:
q.put(NodeWrap(node.left, current_hd - 1))
if node.right is not None:
q.put(NodeWrap(node.right, current_hd + 1))
has to be working solution on Python but for some reasons it fails on 6 test cases from 7 on hackerrank.com. Can somebody explain me why it is happening?
Those people who just run "left" and "right" functions don't understand the task.
def printTopView(root):
lst=[]
current1=root.left
while current1!=None:
lst.append(current1.key)
current1=current1.left
lst.reverse()
current2=root
while current2!=None:
lst.append(current2.key)
current2=current2.right
print(*lst)
Some of the answers above do not work. I tried commenting on them, but, apparently, I don't have the right score, since I've never tried to comment here before.
The problem is that you need to do a breadth first search of the tree to ensure the correct order of the nodes. To exclude "obscured" nodes, another website suggested ranking each node. The root is 0. All branches to the left of a node, have the parent rank, -1. All branches to the right have the parent rank +1. Any nodes with a duplicate rank of its ancestor are excluded.
Then print out the selected nodes in rank order. This will work in all cases.
Python Solution
Solve using Breadth First Traversal
def topView(root):
q = deque()
#Adding root node to the deque along with its Horizontal Distance from root.
q.append([root,0])
#Dictionary to store the {Horizontal Distance: First Node that has this distance}
s = {}
#Breadth First Traversal - [To keep track of the first Node that is visited.]
while q:
temp = q.popleft()
#Horizontal Distance from Root
d = temp[1]
#Adding the Left Child to the Queue (if Exists)
if temp[0].left is not None:
q.append([temp[0].left, d-1])
#Adding the Right Child to the Queue (if Exists)
if temp[0].right is not None:
q.append([temp[0].right, d+1])
#Adding the Horizontal Distance and the First Node that has this distance to Dictionary.
if d not in s:
s[d] = temp[0].info
#Printing out the Top View of Tree based on the values in the Dictionary - From least to Highest Horizontal Distance from Root Node.
for i in sorted(s):
print(s[i], end=" ")

A-Star doesnt behave like it should

I'm quite new to pathfinding and recently got A-Star working for the first time in Java with Libgdx, but it has some flaws, it doesnt always find the fastest path , or the program simply kills itself(because it's too slow?) :/
(Input/Output here: Imgur album: White = untouched Node, green = start, red = target, blue = path, yellow = node is on closed list but unrelevant)
The rest of the code can be found on Github.
This is the code for the Algorithm itself:
Node lastNode;
Node[] neighborNodes;
int lowestF = 2000;
Node bestNode;
public void findPath() {
for(int x = 0; x < map.worldWidth; x++) {
for(int y = 0; y < map.worldHeight; y++) {
nodes[x][y].calculateHeuristic(targetNode);
}
}
lastNode = startNode;
while(lastNode != targetNode || !openList.isEmpty()) {
neighborNodes = map.getNeighbors(lastNode);
for(Node node:neighborNodes) {
if(node != null)
if(node.state != State.BLOCKED && !closedList.contains(node)) {
openList.add(node);
node.parentNode = lastNode;
}
}
lowestF = 1000;
for(Node node:openList) {
if(node.f <= lowestF) {
lowestF = node.f;
bestNode = node;
}
}
if(openList.isEmpty() && bestNode != targetNode) {
System.out.println("No Path possible");
return;
}
openList.remove(bestNode);
closedList.add(bestNode);
lastNode = bestNode;
lastNode.setState(State.SEARCHED);
}
reconstructPath();
}
public void reconstructPath() {
Node lastNode = targetNode;
while(lastNode != startNode) {
lastNode = lastNode.parentNode;
lastNode.setState(State.PATH);
}
setStartAndEnd();
}
And the Node Class:
public class Node {
public enum State {
NORMAL, BLOCKED, START, END, SEARCHED, PATH
}
public State state;
int xPos, yPos;
Color color;
Node parentNode;
int f;
int movementCost = 10;
int heuristic;
public Node(int x, int y) {
xPos = x;
yPos = y;
setState(State.NORMAL);
}
public void setState(State newState) {
state = newState;
}
public boolean isNodeClicked() {
int inputX = Gdx.input.getX();
int inputY = Gdx.graphics.getHeight() - Gdx.input.getY();
if(inputX > xPos*32 && inputX < xPos*32+32 &&
inputY > yPos*32 && inputY < yPos*32+32) {
return true;
}
return false;
}
public void calculateHeuristic(Node targetNode) {
heuristic = (Math.abs((xPos-targetNode.xPos)) + Math.abs((yPos-targetNode.yPos))) * movementCost;
f = movementCost+heuristic;
}
public int calculateHeuristic(Node finishNode, int useless) {
return (Math.abs((xPos-finishNode.xPos)) + Math.abs((yPos-finishNode.yPos))) * movementCost;
}
}
At the moment I'm using a 2-dimensional array for the map or nodes and Arraylist for open and closed list.
It'd be much appreciated if somebody could help me get my A-star to behave and explain to me what I did wrong, I would also be very grateful for any other criticism, since I want to improve my programming :)
Thanks for your help in Advance :)
Your problem is here:
public void calculateHeuristic(Node targetNode) {
heuristic = (Math.abs((xPos-targetNode.xPos)) + Math.abs((yPos- targetNode.yPos))) * movementCost;
f = movementCost+heuristic;
}
Your calculation of your heuristic is wrong, because your calculation of your movementCost is wrong. The cost of a node is not a fixed value. It's the summation of all of the costs to move between nodes along the path to that node so far. So your node should actually have a function,
public int calculateCost(){
if(parentNode != null){
return movementCost + parentNode.calculateCost();
} else{
return movementCost;
}
}
And your heuristic thus becomes:
public void calculateHeuristic(Node targetNode) {
heuristic = (Math.abs((xPos-targetNode.xPos)) + Math.abs((yPos- targetNode.yPos))) * movementCost;
f = calculateCost()+heuristic;
}
Your other problems look like they probably all come from the various typos/logical errors I mentioned in the comments (while(...||openSet.isEmpty()) instead of while(...|| !openSet.isEmpty()), etc)

Splay Tree Search Implementation

I have been trying to learn the ins and outs of some data structures and I am trying to get a binary splay tree to work properly. Every time I run the following code and the node I am looking for is more than one past the root it tells me it is there and then just deletes that whole side from the root down. It works fine if the node is only one level down from the top.
I am not sure what is going wrong but I suppose it has something to do with my rotate functions. I got it to work properly for the insert function which is what I modeled this after.
public class SplayBST {
Node root;
int count;
int level = 0;
boolean found = false;
public SplayBST() {
root = null;
count = 0;
}
public String searchIt(String x) {
//after finishing search method I need to check if splaySearch exists then don't insert just splay it
splaySearch(root, x);
if (this.found == true) {
this.found = false;
return x;
}
else {
return null;
}
}
Node splaySearch(Node h, String x) {
if (h == null) {
return null;
}
if (x.compareTo(h.value) < 0) {
try {
if (x.compareTo(h.left.value) < 0) {
h.left.left = splaySearch(h.left.left, x);
h = rotateRight(h);
} else if (x.compareTo(h.left.value) > 0) {
h.left.right = splaySearch(h.left.right, x);
h.left = rotateLeft(h.left);
}
else {
this.found = true;
return h.left;
}
return rotateRight(h);
}
catch (NullPointerException ex) {
return null;
}
}
else { //basically x.compareTo(h.value)>0
try {
if (x.compareTo(h.right.value) > 0) {
h.right.right = splaySearch(h.right.right, x);
h = rotateLeft(h);
} else if (x.compareTo(h.right.value) < 0) {
h.right.left = splaySearch(h.right.left, x);
h.right = rotateRight(h.right);
}
else {
this.found = true;
return h.right;
}
return rotateLeft(h);
}
catch (NullPointerException ex) {
return null;
}
}
}
Node rotateLeft(Node h) {
Node x = h.right;
h.right = x.left;
x.left = h;
return x;
}
Node rotateRight(Node h) {
Node x = h.left;
h.left = x.right;
x.right = h;
return x;
}
class Node {
Node left;
Node right;
String value;
int pos;
public Node(String x) {
left = null;
right = null;
value = x;
}
}
}
I second Tristan Hull's approach to creating a regular BST with a "working" search method. Once you get that working, adding a splay method is rather trivial. I've actually done the same thing when I implemented a Splay Tree in Java. It's a better software design and a simpler implementation.
Your problem is that when you rotate, you update the reference to node H in the function "SplaySearch", but you do not update the parent node in the original "searchIt" function. Thus, the program "thinks" that the original parent node remains the parent, even though the rotated node should be the parent. Thus, when you run whatever method you use to print your tree, you print from a node that is not actually the parent node of the tree, but a child (the level it is on depends on how many times your program called rotateLeft and rotateRight).
To fix this, I suggest implementing search as in a normal binary tree, and then making a "splay" function completely separate from the search function that splays a node to the top of the tree. You would call this splay function at the end of every search, making sure to properly update your reference. This is the traditional way to implement splay trees, and I suggest you take a look at it (maybe look at the wikipedia article on splay trees or do a Google search). Also, you may want to know that your rotate functions are not complete. In terms of splay trees, you also have 2 separate types of double rotations which are very different from single rotations. Again, I suggest looking up splay trees to learn about them more in depth.

Categories

Resources