Construct a tree from a given array - java

I would like to construct a graph from a given array and root where the node is described below,
static class TreeNode {
private int value;
private ArrayList<TreeNode> children;
public TreeNode(int nodeValue) {
this.value = nodeValue;
this.children = new ArrayList<TreeNode>();
}
public int getValue() {
return this.value;
}
public void addChild(TreeNode child) {
this.children.add(child);
}
public ArrayList<TreeNode> getChildren() {
return this.children;
}
}
An array provided below to construct the graph,
T[0] = 1
T[1] = 2
T[2] = 3
T[3] = 3
T[4] = 2
T[5] = 1
T[6] = 4
Array T describes a network of cities if T[P] = Q and P ≠ Q, then there is a direct road between cities P and Q. If the index of 2 is root, then the graph is provided below,
2 - 3
/ \
1 4
/ | |
0 5 6
Obviously, I can do it manually for the given array,
final int N = 7;
TreeNode[] nodes = new TreeNode[N];
for (int i = 0; i < N; i++) {
nodes[i] = new TreeNode(i);
}
TreeNode root = nodes[2];
root.addChild(nodes[1]);
root.addChild(nodes[3]);
root.addChild(nodes[4]);
nodes[1].addChild(nodes[0]);
nodes[1].addChild(nodes[5]);
nodes[4].addChild(nodes[6]);
How do I construct programmatically when I have given an array and K value? Please help.

After you construct the TreeNode[] array, it's easy:
TreeNode root = null;
for (int i=0; i<T.length; ++i) {
if (T[i] == i) { // if it's a root node
//TODO: Test for multiple root nodes here
root = nodes[i];
} else {
nodes[T[i]].addChild(nodes[i]);
}
}
I would add a private TreeNode parent; object to the TreeNode class, initialize it to null and set it to the parent reference in the addChild method. That's handy to have during debug, even if you don't need it for the first use of this class. Maybe you'll need it later.

Iterate over all nodes,
for each node get the node's value and add the current node to the node at the value.
for (int i = 0; i < N; i++) {
nodes[nodes[i].getValue()].addChild(nodes[i])
}

I write an answer, however, it's not showing all the children. The code is provided below,
public class App {
static class TreeNode {
private int value;
private ArrayList<TreeNode> children;
public TreeNode(int nodeValue) {
this.value = nodeValue;
this.children = new ArrayList<TreeNode>();
}
public int getValue() {
return this.value;
}
public void addChild(TreeNode child) {
this.children.add(child);
}
public ArrayList<TreeNode> getChildren() {
return this.children;
}
}
public static TreeNode buildGraph(int[] T, int K) {
final int N = T.length;
TreeNode[] nodes = new TreeNode[N];
for (int i = 0; i < N; i++) {
nodes[i] = new TreeNode(i);
}
/*
T[0] = 1
T[1] = 2
T[2] = 3
T[3] = 3
T[4] = 2
T[5] = 1
T[6] = 4
2 - 3
/ \
1 4
/ | |
0 5 6
* */
TreeNode root = nodes[K];
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
boolean[] visited = new boolean[N];
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
int index = node.getValue();
visited[index] = true;
// T[3] = 3 is a leaf with no further connection to develop
if (index == T[index]) {
continue;
}
// 2 != 3 for the root node and we havent visited node 3 earlier
if (index != T[index] && !visited[T[index]]) {
node.addChild(nodes[T[index]]);
queue.offer(nodes[T[index]]);
}
int left = 0, right = N - 1;
while (left < index && right > index) {
if (T[left] == index) {
node.addChild(nodes[left]);
queue.offer(nodes[left]);
}
if (T[right] == index) {
node.addChild(nodes[right]);
queue.offer(nodes[right]);
}
left++;
right--;
}
}
return root;
}
public static void main(String[] args) {
int[] T = new int[7];
T[0] = 1;
T[1] = 2;
T[2] = 3;
T[3] = 3;
T[4] = 2;
T[5] = 1;
T[6] = 4;
TreeNode root = buildGraph(T, 2);
System.out.println("The root = " + root.getValue());
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()){
TreeNode node = queue.poll();
ArrayList<TreeNode> children = node.getChildren();
for (int i = 0; i < children.size(); i++) {
TreeNode child = children.get(i);
queue.offer(child);
System.out.println("Parent "+ node.getValue()+ " has children = "+ child.getValue());
}
}
}
}
At the time I run, I get output like,
The root = 2
Parent 2 has children = 3
Parent 2 has children = 1
Parent 1 has children = 0
Anyone can help me to correct how do I miss the other children?
Update
I write it based on the other answer which seems simpler.
public static TreeNode buildGraph1(int[] T, int K) {
final int N = T.length;
TreeNode[] nodes = new TreeNode[N];
for (int i = 0; i < N; i++) {
nodes[i] = new TreeNode(i);
}
/*
T[children] = parent if the children != K
T[0] = 1
T[1] = 2
T[2] = 3
T[3] = 3
T[4] = 2
T[5] = 1
T[6] = 4
2 - 3
/ \
1 4
/ | |
0 5 6
* */
TreeNode root = nodes[K];
int value = root.getValue();
if (T[K] != K) {
nodes[K].addChild(nodes[T[K]]);
}
for (int i = 0; i < T.length; ++i) {
if (K == i) {
continue;
}
if (T[i] != i) {
nodes[T[i]].addChild(nodes[i]);
}
}
return root;
}
The output is provided below:
The root = 2
Parent 2 has children = 3
Parent 2 has children = 1
Parent 2 has children = 4
Parent 1 has children = 0
Parent 1 has children = 5
Parent 4 has children = 6

Related

Sum of all children nodes values in a specific range

I am trying to sum the all children values from its node between a specific range from its root node.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Program {
public static class Node {
int data;
List<Node> children;
public Node(int data) {
this.data = data;
children = new ArrayList<>();
}
public void addChildren(Node... children) {
this.children.addAll(Arrays.asList(children));
}
}
public int sumRange(Node root, int min, int max) {
int sum = 0;
if(root.data >= min && root.data <= max) {
sum = root.value;
}
int size = root.children.size();
for (int i = 0; i < size; ++i) {
if(root.children.get(i).data >= min && root.children.get(i).data <= max) {
sum += sumRange(root.children.get(i), min, max);
}
}
return sum;
}
public static void main(String[] args) {
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node6 = new Node(6);
Node node7 = new Node(7);
Node node2 = new Node(2);
node2.addChildren(node3, node4);
Node node5 = new Node(5);
node5.addChildren(node6, node7);
Node node8 = new Node(8);
Node node1 = new Node(1);
node1.addChildren(node2, node5, node8);
Program program = new Program();
System.out.println(program.sumRange(node1, 3, 5)); // Should print 12
System.out.println(program.sumRange(node2, 3, 5)); // Should print 7
}
}
I have tried this code to calculate the sum of nodes between a specific range:
public int sumRange(Node root, int min, int max) {
int sum = 0;
if(root.data >= min && root.data <= max) {
sum = root.value;
}
int size = root.children.size();
for (int i = 0; i < size; ++i) {
if(root.children.get(i).data >= min && root.children.get(i).data <= max) {
sum += sumRange(root.children.get(i), min, max);
}
}
return sum;
}
And, its summation correctly the only that nodes which have no children. In this line its the node1 have multiple child and it should calculate only the specific range nodes which should sum result 12. But its printing the sum result 5.
System.out.println(program.sumRange(node1, 3, 5)); // Should print 12
I wants to calculate all the child nodes data also. Any help will be appreciated!
The problem is that you only visit child nodes that are within your range. This means if node2 has value 2 its children are never visited and you cannot sum the values 3 and 4. The solution to your problem is removing the if condition in the loop like this:
public int sumRange(Node root, int min, int max) {
int sum = 0;
if(root.data >= min && root.data <= max) {
sum = root.data;
}
int size = root.children.size();
for (int i = 0; i < size; ++i) {
sum += sumRange(root.children.get(i), min, max);
}
return sum;
}
If you try again the output should be 12 for node 1.

Why BFS stuck in Graph Node representation?

I have created graph using Node and Edge class.
When I call traverseBFS method from start = 0. then It just stuck. cannot proceed further. When I use similar approach with HashMap<Integer,ArrayList<Integer>> this algorithm runs properly. Please help me how to fix this.
Complete Code
import java.util.*;
import java.io.*;
public class Dijkstra {
static class Node {
public int id;
public long dist;
public int par;
public Node(int a, long d, int b) {
id = a;
dist = d;
par = b;
}
}
static class Edge {
int to;
int weight;
public Edge(int a, int b) {
to = a;
weight = b;
}
}
static int vert;
static ArrayList<LinkedList<Edge>> list;
static int[] parent;
static long[] distance;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
vert = sc.nextInt();
int edges = sc.nextInt();
list = new ArrayList<>();
parent = new int[vert + 1];
distance = new long[vert + 1];
for (int i = 0; i <= vert; i++) {
list.add(i, new LinkedList<Edge>());
}
for (int i = 0; i < edges; i++) {
int u = sc.nextInt();
int v = sc.nextInt();
int w = sc.nextInt();
list.get(u).add(new Edge(v, w));
list.get(v).add(new Edge(u, w));
}
traverseBFS(0);
}
public static void traverseBFS(int start) {
System.out.print("\nBFS >> \n");
boolean visited[] = new boolean[vert];
LinkedList<Integer> q = new LinkedList<>();
q.add(start);
visited[start] = true;
while (!q.isEmpty()) {
int s = q.poll();
System.out.print(s + " ");
LinkedList<Edge> temp = list.get(s);
for (Edge var : temp) {
if (!visited[var.to]) {
visited[var.to] = true;
q.add(var.to);
}
}
}
}
}
Input
5 6
1 2 2
2 5 5
2 3 4
1 4 1
4 3 3
3 5 1
Output
BFS >>
0
When posting mre consider hard coding test data, to make it easier to run a test:
public static void main(String[] args) {
int[][] neighbours = {
{1,2,2},
{2,5,5},
{2,3,4},
{1,4,1},
{4,3,3},
{3,5,1}
};
vert = 5;
list = new ArrayList<>();
parent = new int[vert + 1];
distance = new long[vert + 1];
for (int i = 0; i <= vert; i++) {
list.add(i, new LinkedList<Edge>());
}
for (int i = 0; i < neighbours.length; i++) {
int u = neighbours[i][0];
int v = neighbours[i][1];
int w = neighbours[i][2];
list.get(u).add(new Edge(v, w));
list.get(v).add(new Edge(u, w));
}
traverseBFS(0);
}
A simple print out the graph created shows that node 0 is not connected to any other node:
Node 0 connected: []
Node 1 connected: [to 2, to 4]
Node 2 connected: [to 1, to 5, to 3]
Node 3 connected: [to 2, to 4, to 5]
Node 4 connected: [to 1, to 3]
Node 5 connected: [to 2, to 3]
To simplify the printout add toString method to Edge:
static class Edge {
int to;
int weight;
public Edge(int a, int b) {
to = a;
weight = b;
}
#Override
public String toString() {
return "to "+to;
}
}
and use
for(int node = 0; node < list.size(); node ++){
System.out.println("Node "+node +" connected: " + list.get(node));
}

Why doesn't Dijkstra's algorithm work as it should for given graph?

I have the following code, Dijkstra's algorithm, that I made using Wikipedia's article on the algorithm.
For the given graph (see image) and starting node (1), it returns 5 as distance to node (4), which is obviously false. However, when going from node (4), it returns 4 as distance to (1), which is correct. What is wrong in my code?
//source = starting point, adj[] = adjacency list
private static int dijkstra (int source, ArrayList<Road>[] adj) {
HashSet<Integer> vertices = new HashSet<>();
int[] dist = new int[adj.length];
int[] prev = new int[adj.length];
for (int i = 0; i < adj.length; i++) {
dist[i] = Integer.MAX_VALUE;
prev[i] = Integer.MAX_VALUE;
vertices.add(i);
}
dist[source] = 0;
while (!vertices.isEmpty()) {
int current = Integer.MAX_VALUE;
for (int v: vertices) {
if (dist[v] < current) {
current = v;
}
}
vertices.remove(current);
for (Road v: adj[current]) {
int alt = dist[current] + v.distance;
if (alt < dist[v.end]) {
dist[v.end] = alt;
prev[v.end] = current;
}
}
}
}
class Road {
int end;
int distance;
}
//This loop builds adjacency list from input such as "1 3 2", where 1 represents
// starting node, 3 represents end node and 2 represents weight of that edge.
//start and end values are decremented in order to be 0-indexed
for (int i = 0; i < M; i++) {
int start = in.nextInt() - 1;
int end = in.nextInt() - 1 ;
int dist = in.nextInt();
adj[start].add(new Road(end, dist));
adj[end].add(new Road(start, dist));
}
This piece of code is causing the error:
int current = Integer.MAX_VALUE;
for (int v: vertices) {
if (dist[v] < current) {
current = v;
}
}
I assume it's supposed to search the unvisited node that has the shortest path from the start-vertex. But this should look rather like this:
int currentPathLen = Integer.MAX_VALUE, current = -1;
for (int v: vertices) {
if (dist[v] < currentPathLen) {
current = v;
currentPathLen = dist[current];
}
}

implementing Dijkstra's Algorithm using priority queue

I'm implementing Dijkstra's Algorithm using priority queue, I want a function to remove an element from the heap but I can only send it the vertex index from the Dijkstra's main and I can't find its position on the heap and I can't afford to do a binary search. Any ideas?
public class MinHeap {
Vertex[] Heap = null; // Vertex array
int Lenght;
int Size;
int[] elementsPostion; // Array of Index of Vertices
private int parent(int i) {
if (i % 2 == 0)
return (i / 2) - 1;
else
return i / 2;
}
private int leftChild(int i) {
return (2 * i) + 1;
}
private int rightChild(int i) {
return (2 * i) + 2;
}
// Initialize PQ
public MinHeap(int len) {
Lenght = len;
Size = 0;
Heap = new Vertex[Lenght];
elementsPostion = new int[Lenght];
}
// Extract Min
public Vertex ExtractMin() {
Vertex v;
v = Heap[0]; // min = index of min
elementsPostion[Heap[0].index] = -1;
Heap[0] = Heap[Size - 1];
elementsPostion[Heap[0].index] = 0;
Size = Size - 1;
minHeapify(0);
return v;
}
// ----------------------------
// Sort Inside PQ
public void minHeapify(int pos) {
int L;
int R;
L = leftChild(pos);
R = rightChild(pos);
while (pos < Size
&& (Heap[L].minDistance < Heap[pos].minDistance || Heap[R].minDistance < Heap[pos].minDistance)) {
Vertex tmp;
if (Heap[L].minDistance < Heap[R].minDistance) {
elementsPostion[Heap[L].index] = pos;
elementsPostion[Heap[pos].index] = L;
tmp = Heap[L];
Heap[L] = Heap[pos];
Heap[pos] = tmp;
pos = L;
} else {
elementsPostion[Heap[R].index] = pos;
elementsPostion[Heap[pos].index] = R;
tmp = Heap[R];
Heap[R] = Heap[pos];
Heap[pos] = tmp;
pos = R;
}
L = leftChild(pos);
R = rightChild(pos);
/*
* if(pos< Size && Heap[L].minDistance <Heap[pos].minDistance)
* min=L.index; else min=pos; if(R.index<=Size &&Heap[R]<Heap[pos])
* min=R.index; if(min !=pos) { int tmp = Heap[pos]; Heap[pos] =
* Heap[min]; Heap[min] = tmp; minHeapify(min); }
*/
}
// swap in P.Q with Swapping in arrayofVertNum
}
// insert vertex
public void insertVertex(Vertex element) {
Heap[Size] = element; // size = number of verticies
HeapDecreaseKey(Size, element); //
Size++;
}
// Compare when insert with Parents
public void HeapDecreaseKey(int index, Vertex key) // bta5od el element ele hy3mlo insert ,,
{
// index=size , key=element // add in last
// Heap[index]=key; //add in last
Vertex v = new Vertex(key.index, key.xPos, key.yPos, key.minDistance);
//int swap;
boolean b = false;
while (index > 0
&& Heap[parent(index)].minDistance > Heap[index].minDistance) {
b = true;
elementsPostion[Heap[parent(index)].index] = index;
elementsPostion[Heap[index].index] = parent(index);
Vertex tmp = Heap[parent(index)];
Heap[parent(index)] = Heap[index];
Heap[index] = tmp;
index = parent(index);
}
if (b == false)
elementsPostion[key.index] = index;
// Swap in array
}
// check if PQ is empty
public boolean isEmpty() {
return Heap == null;
}
public void display() {
for (int i = 0; i < Size; i++) {
System.out.print(Heap[i].minDistance);
}
System.out.println();
}
}
Keep track of the vertex in the heap using simple index array Positions[Vertex] and record (Vertex,Distance) as element in heap array. But implementing only this is not enough because you need to update positions of vertex very time you do swap operation on heap in any routine.

Implementing Dijkstra's algorithm using min-heap but failed

I am trying to implement Dijkstra's Algorithm using min-heap in java but getting wrong output every time. Here i fount the same topic in C++. Below is my graph. Node A, which is green colored, is source and Node F, which is red colored, is destination. My objective is to find out the shortest path length from A to F.
Below is my code
public class Dijkstra {
private static Heap heap = new Heap();
private static int[][] graph;
public Dijkstra() {
graph = new int[6][6];
/*
* The graph value assignment is just for checking the code. node A is
* referred as node 0, node B is referred as node 1 and so on. finally
* node F is referred as node 5.
*/
graph[0][0] = graph[0][1] = graph[0][3] = graph[0][4] = graph[0][5] = graph[1][0] = graph[1][1] = graph[1][4] = graph[1][5] = graph[2][2] = graph[2][5] = graph[3][0] = graph[3][3] = graph[4][0] = graph[4][1] = graph[4][4] = graph[5][0] = graph[5][1] = graph[5][2] = graph[5][5] = 0;
graph[1][2] = graph[2][1] = graph[2][3] = graph[3][2] = graph[3][4] = graph[4][3] = graph[4][5] = graph[5][4] = 1;
graph[1][3] = graph[3][1] = 3;
graph[0][2] = graph[2][0] = 4;
graph[2][4] = graph[4][2] = 5;
graph[3][5] = graph[5][3] = 8;
}
public static void main(String[] args) {
Dijkstra dij = new Dijkstra();
// Source is node A (node 0) and destination is node F (node 5)
System.out.println(dij.solve(6, 0, 5));
}
public int solve(int numOfNodes, int source, int dest) {
heap.push(source, 0);
while (!heap.isEmpty()) {
int u = heap.pop();
if (u == dest)
return heap.cost[dest];
for (int i = 0; i < numOfNodes; i++) {
if (graph[u][i] >= 0)
heap.push(i, heap.cost[u] + graph[u][i]);
}
}
return -1;
}
}
class Heap {
private int[] data;
private int[] index;
public int[] cost;
private int size;
public Heap() {
data = new int[6];
index = new int[6];
cost = new int[6];
for (int i = 0; i < 6; i++) {
index[i] = -1;
cost[i] = -1;
}
size = 0;
}
public boolean isEmpty() {
return (size == 0);
}
private void shiftUp(int i) {
int j;
while (i > 0) {
j = (i - 1) / 2;
if (cost[data[i]] < cost[data[j]]) {
// swap here
int temp = index[data[i]];
index[data[i]] = index[data[j]];
index[data[j]] = temp;
// swap here
temp = data[i];
data[i] = data[j];
data[j] = temp;
i = j;
} else
break;
}
}
private void shiftDown(int i) {
int j, k;
while (2 * i + 1 < size) {
j = 2 * i + 1;
k = j + 1;
if (k < size && cost[data[k]] < cost[data[j]]
&& cost[data[k]] < cost[data[i]]) {
// swap here
int temp = index[data[k]];
index[data[k]] = index[data[i]];
index[data[i]] = temp;
// swap here
temp = data[k];
data[k] = data[i];
data[i] = temp;
i = k;
} else if (cost[data[j]] < cost[data[i]]) {
// swap here
int temp = index[data[j]];
index[data[j]] = index[data[i]];
index[data[i]] = temp;
// swap here
temp = data[j];
data[j] = data[i];
data[i] = temp;
i = j;
} else
break;
}
}
public int pop() {
int res = data[0];
data[0] = data[size - 1];
index[data[0]] = 0;
size--;
shiftDown(0);
return res;
}
public void push(int x, int c) {
if (index[x] == -1) {
cost[x] = c;
data[size] = x;
index[x] = size;
size++;
shiftUp(index[x]);
} else {
if (c < cost[x]) {
cost[x] = c;
shiftUp(index[x]);
shiftDown(index[x]);
}
}
}
}
While running this whole code, i am getting 0 as output but one can clearly tell the cost from node A to node F is 7 (4+1+1+1 = A-C-D-E-F). Where is the error?
You test for an existing edge using graph[u][i] >= 0. But your graph is defined to have no edge for value zero. So you should change it to
if (graph[u][i] > 0) ...
inside method solve. Another possibility is to mark non-existing edges with a value of -1 in your matrix. This would then also allow for zero-cost edges.
In the heap, you have two values:
index that identifies the node,
and cost that identify the distance of the node.
You pop the cost, that is the distance, but you used it like the index to identify the node.
public int pop() {
int res = data[0];
...
return res;
}
and in solve():
int u = heap.pop();
if (u == dest)
...

Categories