On the web there is the solution for printing the values, like this:
void printPostorder(Node node)
{
if (node == null)
return;
// first recur on left subtree
printPostorder(node.left);
// then recur on right subtree
printPostorder(node.right);
// now deal with the node
System.out.print(node.key + " ");
}
But my problem is that I don't want to print the values but put them in an ArrayList. That part is easy I've tried to use ArrayList.add instead of System.out.print, but my struggle is that I want to return it so instead of void my return type will be ArrayList. The problem is that I don't know what to return in the base case:
if (node == null)
return;
My method does return an ArrayList so what can I return for the base case above?
In the end case you could return an empty list, and accumulate the results by calling addAll:
List<Node> getPostOrderList(Node node) {
List<Node> retVale = new ArrayList<>();
if (node == null) {
return retVal;
}
// first recur on left subtree
retVal.addAll(getPostOrderList(node.left));
// then recur on right subtree
retVal.addAll(getPostOrderList(node.right));
// now deal with the node
retVal.add(node);
return retVal;
}
Related
I`m trying to implement my own linkedlist and I tackled with this question.
This is add method implementation for linkedlist, supposed to add specified elements to the end of the list.
Below you see a code I found and that works, and you see my code which only shows last 2 elements added no matter how many you add to the list.
The only difference 2 codes have is that he stores rootNode (head) inside currentNode and does his traversing using currentNode. I directly used rootNode to do the same. Can someone explain my what is wrong with my code ?
This is his code that works:
public void add (E val) {
Node newNode = new Node(val, null);
Node currentNode = rootNode;
if (rootNode == null) {
rootNode = newNode;
} else {
while (currentNode.nextNode != null) {
currentNode = currentNode.nextNode;
}
currentNode.setNextNode(newNode);
}
}
And this is my code that only shows last 2 elements added :
public void add (E val) {
Node newNode = new Node(val, null);
if (rootNode == null) {
rootNode = newNode;
} else {
while (rootNode.nextNode != null) {
rootNode = rootNode.nextNode;
}
rootNode.setNextNode(newNode);
}
}
That happens because you're resigning the rootNode while iterating.
By making this, you are erasing all previous state of the list, which you can access only via root. That's way the only node that remain in the list are root and its next node.
In order to iterate over the list, you should introduce the local variable like in the first version. There's no other way around.
And I suggest to simplify the method a bit by returning after checking whether the root is null, there will be no in nesting the loop into the additional block of curly braces:
public void add (E val) {
Node newNode = new Node(val,null);
if(rootNode == null) {
rootNode = newNode;
return;
}
Node currentNode = rootNode;
while (rootNode.nextNode != null) {
rootNode = rootNode.nextNode;
}
rootNode.setNextNode(newNode);
}
Because you are changing root node, after add method ends, you have only the root node and the next node of it, do not change root node if it is not null.
For instance, you call add Method for nodes A, B, and C.
For the first time root is A, then when you call add(B), as the root node is not null already, loop will not work in the else statement and the next of A will be B, then when you call add(C), while loop will work one iteration and B will become root node(you lost A) and the next of B will be C node.
I can merge the two descending singly linkedlists into one descending list with just one recursion, but I don't know how to do to make the result ascending instead without creating any helper methods.
This is my code for merging them into descending order. I was trying to modify within this code to make it ascending but failed. Please help me out~
public Node mergeByRecursion(Node node1, Node node2) {
if (node1 == null) {
return node2;
} else if (node2 == null) {
return node1;
}
if (node1.value < node2.value) {
node1.next = merge(node1.next, node2);
return node1;
} else {
node2.next = merge(node1, node2.next);
return node2;
}
}
Here is a picture of the detailed question that I am trying to solve.
UPDATE
I have figured out a solution that works, but not sure if it is the best solution and fits the requirement 100% so I made another post for asking a code review. In case, anyone also gets stuck by this question wanna know a potential solution.
Code Review
I guess maybe this would work:
public Node mergeByRecursion(Node node1, Node node2) {
if (node1 == null) {
return node2;
}
if (node2 == null) {
return node1;
}
if (node1.getElement().value < node2.getElement().value) {
node1.getNext() = mergeByRecursion(node1.getNext(), node2);
return node1;
} else {
node2.getNext() = mergeByRecursion(node1, node2.getNext());
return node2;
}
}
You probably don't need to use head_node var.
You can just call getNext() since the lists are already sorted.
I have got a graph, and I would like to find a path between two nodes (number 3 and 5).
I read about finding paths in graph, and I tried to write DFS and BFS. Both are implemented and works well. However, I would like to get a list of each node visited directly from 3 to 5.
Both algorithms work as they supposed to so, when running bsf I will visit nodes in such order: 2,6,1,4,5.
Using dfs 2,1,4,5.
But what I would like to do achieve is 6,5 (in first case) and 2,4,5 in second.
In other words, I want to save only nodes that are on the way from 3 to 5 (Not all visited during dfs/bfs), as a List of nodes.
I have been racking my brain for a long time, how to change my code to achieve it, or maybe should i change my approach? I should should store nodes in the correct path, or use different algorithm? I simply do not have idea how to do it.
My bfs
public List<Node> bfs(Node root, Node nodeWeSearchFor)
{ Queue<Node> queue = new LinkedList<Node>();
List<Node> route = new ArrayList<Node>();
if(root == null || nodeWeSearchFor == null) return route;
//State is just an enum Visited or unvisited
root.state = State.Visited;
//Adds to end of queue
queue.add(root);
while(!queue.isEmpty())
{
//removes from front of queue
Node r = queue.remove();
//Visit child first before grandchild
for(Node n: r.getConnectedNodes())
{
if(n.state == State.Unvisited)
{
queue.add(n);
route.add(n);
n.state = State.Visited;
//If we found node, return
if(n==nodeWeSearchFor){
return route;
}
}
}
}
return route;}
My dfs:
public List<Node> dfs(Node root, Node nodeWeSearchFor)
{
List<Node> route = new ArrayList<Node>();
//Avoid infinite loops
if(root == null) return route;
System.out.print(root.toString() + "\t");
root.state = State.Visited;
route.add(root);
if(root == nodeWeSearchFor) return route;
//for every child
for(Node n: root.getConnectedNodes())
{
//if childs state is not visited then recurse
if(n.state == State.Unvisited)
{
//recursive call for dfs (We are passing route)
dfs(n,nodeWeSearchFor,route);
}
}
return route;
}
public List<Node> dfs(Node root, Node nodeWeSearchFor,List<Node> _route)
{
List<Node> route = _route;
//Avoid infinite loops
if(root == null) return route;
System.out.print(root.toString() + "\t");
root.state = State.Visited;
route.add(root);
if(root == nodeWeSearchFor) return route;
//for every child
for(Node n: root.getConnectedNodes())
{
//if childs state is not visited then recurse
if(n.state == State.Unvisited)
{
dfs(n,nodeWeSearchFor,route);
}
}
return route;
}
It is quite easy, in DFS, when you reach the "end" (you cannot go forward), you have to "go back". So when you are going "back", you just remove that node at the "dead end" from your list of visited nodes.
In BFS, you have to create new list for each node visited, copy the already visited nodes of node that "opens him" and then add itself to that list.
I am writing a simple recursive code to reverse a linked-list in Java. Strangely it returns the same node.
Node reverse(Node ptr) {
if (ptr.link == null)
return ptr;
Node second = ptr.link;
ptr.link = null;
Node rest = reverse(second);
rest.link = ptr;
return rest;
}
Why isn't this working?
Your current approach won't work, the rest value that's being returned from the recursive call doesn't point to the last element in the list (which should be the insertion point for the nodes), instead it's pointing to the first element of the result. In other words, this line isn't correctly building the output:
rest.link = ptr;
For successfully reversing a list, one strategy is to use an accumulator parameter, so we can insert at the head of the list as the recursion unwinds - bear in mind that the recursion starts to "go back" in reverse order with respect to the elements in the list. Try this, it's a tail-recursive solution:
Node reverse(Node ptr, Node acc) {
if (ptr == null)
return acc;
Node second = ptr.link;
ptr.link = acc;
return reverse(second, ptr);
}
Call the above method like this:
Node reversedList = reverse(list, null);
Be aware that the input list will be modified in-place and won't be the same after the method returns, any variable that holds a reference to list will be affected. If that's a problem, you should create a copy of list before passing it to reverse().
Oscar is correct that the return value from recursive call does not point to the last element.
There is another algorithm that does not use accumulator parameter:
function reverse(node) {
if (node.next == null)
return node;
var tail = reverse(node.next);
node.next.next = node;
node.next = null;
return tail;
}
Node reverseNode(Node node){
Node head = null;
While(node.next != null){
Node n = new Node(node.data);
n.next = head;
head = n;
node = node.next;
}
return head;}
You know you don't have to write a recursive function
I am unable to get my program to delete the last node or only node in my linked list. It will delete any other node. This program allows the user to enter integers and delete them. Thanks in advance for your help.
// This method finds the value requested in the Linked List.
public Node find(Node head, Comparable value2){
if (head == null )
{
System.out.println("The list is empty");
return null;
}
Node pointer = head;
while (pointer != null)
{
if (pointer.data.compareTo(value2)>=0)
{
Node delNode = pointer;
System.out.print("Found it. Deleting " + delNode.data + "\n");
return delNode;
}
pointer = pointer.next;
}
return null;
}
// This method deletes a given value from the linked list.
public void delete(Node head, Comparable value2){
Node delNode;
delNode = find(head, value2);
if (delNode== null)
{
System.out.println("The value: " + value2 + " does not exist");
print(head);
}
else
{
if (delNode.next == null)
{
System.out.println("Trying to delete last");
delNode = null;
print(head);
}
else{
delNode.data = delNode.next.data;
Node temp = delNode.next.next;
delNode.next = null;
delNode.next = temp;
print(head);
}
}
return;
}
I thought that if (delNode.next== null) {delNode = null} would do it?
If you want to delete a node, you should have a reference to the node before the one you want to delete, say beforeNode, and set
beforeNode.next = beforeNode.next.next;
(Think about special cases like deleting the last element.)
See Java Linked List search and delete method
Please note that in the sequence
delNode.next = null;
delNode.next = temp;
The first line is useless.
You current delete operation effectively works by copying the next node into the current node and then deletes the next node, making it look like you deleted the current node. This is fine until there is no next node, as you have discovered.
The reason the following doesn't work
if (delNode.next == null)
{
System.out.println("Trying to delete last");
delNode = null;
print(head);
}
is that delNode is just a local variable, setting delNode to null doesn't affect anything outside of delete().
If you want to delete the last node from the list, you need to set the next pointer in the second last element to null. Therefor it is insufficient for find() to simply return the element you wish to delete -- you need the previous element.
Pseudocode for delete(data) should be (untested):
if head == null
return
if head.data == data
head = head.next
return
previous = find_previous(data)
if previous == null
return
previous.next = previous.next.next