Hi I am trying to print out level order of a binary search tree in the format (node element, parent node element). I am currently using queues to get the level order but I am having a hard time getting the parent node. Is it possible to do with queues? If so how would I go about doing it? If not what is a more optimal way of doing it? Thank you!
For example with the following tree:
6
/ \
5 7
Level 0: (6, null)
Level 1: (5, 6) (7, 6)
So unfortunately there isn't a way of doing this strictly with one queue, assuming your nodes only have a left,right, and value. The problem is once you get to depths > 0, the nodes at that level might have different parents, and that information is gone unless you store it in some fashion.
The easy way to do this is to just add a Node parent inside of your Node class. Barring that, you could also make a inner class that holds the mapping of the Node to parent node, or you could use any number of data structures. Below I included how to do this with hashmaps.
public void printLevelOrder(){
Queue<Node> q = new LinkedList<Node>();
Map<Node, Node> parents = new HashMap<Node,Node>();
Node nextLevel = null;
q.add(this);
int lvl = 0;
while (!q.isEmpty()){
Node n = q.remove();
if (n == nextLevel || nextLevel == null){
System.out.print("\nlvl " + lvl++ +" ");
nextLevel = null;
}
System.out.print("("+n.value +","+parents.remove(n)+")");
if (n.left != null){
q.add(n.left);
parents.put(n.left, n);
if (nextLevel == null)
nextLevel = n.left;
}
if (n.right != null){
q.add(n.right);
parents.put(n.right, n);
if (nextLevel == null)
nextLevel = n.right;
}
}
}
To print the nodes by level I do the following. The next level is determined by adding the first non null nextLevel node. When we have reached that node, we know we are at the start of the next line, and null it out again.
Related
I implemented public BinarySearchTree<Node,T> chop(T x)
that chops my tree into two parts at element x. The SSet this will contain elements < x, and the returned SSet is a SSet that contains elements >= x. This should work for all elements regardless of whether they are in this.
For example, suppose s={2,4,6,8}. Then s.chop(3) returns {4,6,8} and s becomes {2}. We would get the same result for s.chop(4).
The slowChop method is implemented, but it has a time complexity of O(n), but I need to reduce it to at least O(h) when the tree is balanced (where h is the height of the tree).
public BinarySearchTree<Node,T> slowChop(T x) {
Node sample = super.newNode();
BinarySearchTree<Node,T> other = new
BinarySearchTree<Node, T>(sample);
// Iterate through the n nodes in-order.
// When see value >=x, add to new BST in O(height) time, and
// remove it from this BST (on next iteration) in O(height) time.
Iterator<T> it = iterator();
T prev = null;
while( it.hasNext() ) {
T curr = (T)(it.next());
if( c.compare(curr, x) >= 0 ) { // we have our first >= x
other.add(curr);
if( prev != null ) {
this.remove(prev); // safe to remove now
}
prev = curr;
}
}
if( prev != null ) {
this.remove(prev); // edge case, get that last one!
}
return other;
}
public BinarySearchTree<Node,T> chop(T x) {
Node sample = super.newNode();
BinarySearchTree<Node,T> other = new
BinarySearchTree<Node, T>(sample);
// TODO: Implement this method. It should match slowChop in
// behaviour, but should be faster :-)
return other;
}
Indeed, your algorithm is not making use of the efficiency that you can get from the fact you are dealing with a binary search tree. So iterating through the tree with an in-order traversal is not the way to go.
Instead, perform a binary search and cut the edges that link two nodes which should end up in different trees. While cutting you'll also need to reattach nodes to where a previous cut was performed. The complexity is the same as a binary search towards the bottom of the tree, and so it is O(logn).
Here is an implementation that assumes you have the regular getters and setters:
on the Node class: getLeft, setLeft, getRight, setRight, getValue, and
on the BinarySearchTree class: getRoot, setRoot
public BinarySearchTree<Node,T> chop(T x) {
// Create two temporary dummy (sentinel) nodes to ease the process.
Node rightRootParent = super.newNode();
Node leftRootParent = super.newNode();
// Set "cursors" at both sides
Node rightParent = rightRootParent;
Node leftParent = leftRootParent;
// Start the binary search for x, cutting edges as we walk down
Node node = this.getRoot();
while (node != null) {
// Decide for each node in the binary search path at which side it should go
if (c.compare(node.getValue(), x) >= 0) {
// Node should belong to the right-side tree
rightParent.setLeft(node); // Establish edge
rightParent = node;
node = node.getLeft(); // Move down
rightParent.setLeft(null); // Cut next edge for now (it might get restored)
} else { // Symmetric case
leftParent.setRight(node);
leftParent = node;
node = node.getRight();
leftParent.setRight(null);
}
}
// Set the roots of both trees
this.setRoot(leftRootParent.getRight());
return BinarySearchTree<Node, T>(rightRootParent.getLeft());
}
So I'm building this tree which has 1..* Nodes where each node has a list which in themselves can have 1..* nodes.
The first three levels of the tree I can build just fine but then it won't work more if I don't code all the levels which are just plain stupid. The solution is of course to use some kind of recursive method and a BFS.
Basically, in my TreeBuilder class, I want to be able to call tree.getNodesAtDepth(depth)) and get a list of all nodes that are at that depth. Problem is that I don't understand how I can implement the getNodesAtDepth(depth) method.
All the examples I find are for binary trees. An alternative is to have the addChild method take a depth argument so I can specify at which depth to insert the child at.
In the end, this is what I want:
I have a tree with a root. The root has a list which has 4 children nodes. I want to get the 4 children. For each child generate three nodes. So for child 0 has 3 children, child 1 has 3 children, child 3 has 3 children and child 4 has 3 children. And so forth
Maybe a possible soultion is to have a level attribute on each node and search for that node and then return it's parent. Beacuse it's parent should have a list of all the nodes at the searched for node.
Try this method :
static void getNodesAtDepth(Node root, int currentLevel, int level, List<Node> nodes) {
if(root == null) return;
if(level == 0) {
nodes.add(root);
return;
}
if(currentLevel + 1 == level) {
if(root.getNodeList() != null) {
nodes.addAll(root.getNodeList());
}
}
if(currentLevel < level) {
if(root.getNodeList() != null) {
for(Node node : root.getNodeList()) {
getNodesAtDepth(node, currentLevel + 1, level , nodes);
}
}
}
}
How to use it :
List<Node> nodeList = new LinkedList<>();
getNodesAtDepth(root, 0, 2, nodeList);
root of course is the root of your tree. nodeList will store all your nodes at desired level (in my case it's 2). Second parameter is always 0, (that's for keeping track of the current level)
If I assume your class tree structure is :
class Tree {
List<Tree> children
...
}
Then you can recursively iterate through the tree until you find the expected depth:
void recursivelyCollectNodesAtDepth(int depth,
List<Tree> nodesAtDepth,
Tree tree,
int currentDepth) {
if (tree == null) {
return;
}
if (depth == 0) {
nodesAtDepth.add(tree);
} else if (currentDepth + 1 == depth) {
// add children to the node list when expected depth is reached
if (tree.getChildren() != null) {
nodesAtDepth.addAll(tree.getChildren());
}
} else if (currentDepth < depth) {
// iterate and recursively travers through child nodes
for (Tree childTree : tree.getChildren()) {
recursivelyCollectNodesAtDepth(depth,
nodesAtDepth,
childTree,
currentDepth + 1);
}
}
}
Here the tree nodes a recursively traversed to the expected level
I am currently doing a Cracking the Coding Interview Problem (2.4) and I am supposed to partition a linked list around a value x, such that all nodes less than x come before all nodes greater than or equal to x. However, I am really confused as to why a temporary variable "next" is needed and why is node.next nulled below it. Why can't I just do node = node.next at the end of the while loop?
I am simply creating two linked lists, before and after, and merging them together once the correct values are put into each list.
public static Node partition(Node node, int x) {
Node beforeStart = null;
Node beforeEnd = null;
Node afterStart = null;
Node afterEnd = null;
/* Partition list */
while (node != null) {
Node next = node.next;
node.next = null;
if (node.data < x) {
if (beforeStart == null) {
beforeStart = node;
beforeEnd = beforeStart;
} else {
beforeEnd.next = node;
beforeEnd = beforeEnd.next;
}
} else {
if (afterStart == null) {
afterStart = node;
afterEnd = afterStart;
} else {
afterEnd.next = node;
afterEnd = afterEnd.next;
}
}
node = next;
}
/* Merge before list and after list */
if (beforeStart == null) {
return afterStart;
}
beforeEnd.next = afterStart;
return beforeStart;
}
Why can't I just do node = node.next at the end of the while loop?
It can be done this way. After doing the partition, for each list, you need to set the last node's next pointer to NULL. This will just take two lines of code.
The example code is using next = node.next and node.next = NULL to terminate each list during the partition process, but in this case that's not needed, since the lists don't need NULL terminators until after the partition process is done.
The loop in your question removes nodes from the head of the original list, and appends them to the before list or the after list, until the original list is empty. Then it concatenates the before and after lists.
That's easy to explain and easy to understand.
It can be done without the temporary next or nulling out node.next in every iteration, but then the above description would no longer apply -- nodes would not be removed from the original list in every iteration, the before list and after list would not contain only the appropriate nodes, the operation you perform on them is not 'appending', and nodes would even appear in multiple lists for a while.
Your algorithm would suddenly be a lot more difficult to describe and understand. That is a bad thing in software development, and a bad thing in a coding interview.
I am already aware of various answers to this question. But I have a very confusing bug in my code. The following is a series of println() calls to see if the list I created is correctly sorted.
ListNode list_b = new ListNode(3, new ListNode(-2));
System.out.println("Checking the string conversion: " +
sut.convertToString(list_b)); //output is 3,-2, as expected. Expected result of sorting is -2,3.
System.out.println("Now checking the
string conversion of the sorted list: " +
sut.convertToString(sut.sort(list_b, int_comparator))); //output is -2,3 as expected.
System.out.println("Now this is list_b following the sorting,
by calling the element and next directly: "
+ list_b.element + "," + list_b.next); //3,null. How the hell did that happen!?!??!!?
The convertToString method is as follows:
public String convertToString(ListNode head) {
if (head != null) {
String representation = "";
if (!head.element.equals(null))
representation += head.element.toString();
ListNode next = null;
if (head.next != null)
next = head.next;
if (next != null && !next.element.equals(null))
representation += "," + next.element.toString();
while (next != null) {
if (next.next != null) {
next = next.next;
if (!next.element.equals(null))
representation += "," + next.element.toString();
}
else
break;
}
return representation;
}
else
return "";
}
And the actual sort method is still a work in progress, albeit fairly simple:
public ListNode sort(ListNode head, Comparator comparator) {
if (head != null) {
ListNode next = null;
if (head.next != null)
next = head.next;
else
return head;
if (comparator.compare(head.element, next.element) > 0) {
head.next = next.next;
next.next = head;
head = next;
}
return head;
}
return null;
}
Would anyone care to explain how I've managed to do the seemingly impossible? I'm speechless at how this could happen! Many thanks to anyone who can explain!
EDIT: thank you to those for your answers and suggestions. I should clarify that the following tests are then performed on the list:
assertTrue(sut.deepEquals(list_a, sut.sort(list_a, int_comparator)));
assertFalse(sut.deepEquals(list_b, sut.sort(list_b, int_comparator)));
assertTrue(sut.deepEquals(new ListNode(-2, new ListNode(3)), sut.sort(list_b, int_comparator)));
assertTrue(sut.deepEquals(new ListNode(-14, new ListNode(-2, new ListNode(3))), sut.sort(list_c, int_comparator)));
Clearly, this implies that any updating of list_b (i.e. list_b = sut.sort(list_b)) is unnecessary. What I'm asking is how you would change the sort method itself so that updating is unnecessary.
Pretty simple: you sort the list in this piece of code:
sut.convertToString(sut.sort(list_b, int_comparator)))
The list is transformed this way:
3 -> -2 -> null ====> -2 -> 3 -> null
^ ^
| |
list_b list_b
sut.sort returns the new front (head) of the list, which should be the new list_b, but since you don't update the value, it points to the second node in the list, thus producing "3 , null"
Well ... you are changing the internals of the passed node inside your sort method. The variable list_b is still referring to the node "3" that after sorting does not have a successor anymore.
Your sort method is returning the new head of the sorted list. But you do not use that afterwards!
Change your code snippet to:
list_b = sut.sort(list_b, int_comparator);
System.out.println(sut.convertToString(list_b));
list_b references the node containing 3, and having the node 2 as next element.
Then you sort the list. That changes the node containing 3: its next node is now null, since it becomes the last element of the list. It also changes the node 2, which now has the node 3 as next element. But list_b continues to be a reference to the node containing 3.
When you print the node list_b, you thus get 3, null as a result.
EDIT:
to answer your last question:
how you would change the sort method itself so that updating is unnecessary
You should have an actual LinkedList class (exactly as the standard java.util.LinkedList class). The class you have doesn't represent a list. It represents a node inside a chain of nodes.
The LinkedList class would have a reference to the head node, and would contain all the methods needed to iterate through the values stored in the list, transform it to a String, sort it, etc. Of course, sorting the list would imply changing the reference to the head node inside the LinkedList object. But that would be transparent to the user of the LinkedList class, which would never manipulated nodes directly.
Of course, if you start caring so much about having a proper LinkedList class, you should simply use the standard one, which is standard, documented, and tested.
Hi I have a tree in which I would like to get paths from the initial (root) node to all leaves.
I found several algortithms that list (all) apths betwenn any given two nodes within a graph (for example this SO question:
Graph Algorithm To Find All Connections Between Two Arbitrary Vertices)
For binary tree there also exists an algorithm
http://techieme.in/print-all-paths-in-a-tree/
but I work on a tree with various branching factors.
Is there any better way of achieving what I want to do than traversing the tree once in order to get all leaves and then run the algorithm above for all leaves combined with the initial node?
I was thinking about implementing simple DFS extended by some additional stack containing all nodes alongt he path to a single leaf and then listing all sentences by looping through these stacks.
ArrayList<GrammarNode> discovered = new ArrayList<GrammarNode>();
Stack<GrammarNode> S = new Stack<GrammarNode>();
while (!S.empty()) {
node = S.pop();
if (!discovered.contains(node)) {
discovered.add(node);
System.out.println(node.getWord.getSpelling().trim());
for (GrammarArc arc : node.getSuccessors()) {
S.push(arc.getGrammarNode());
}
}
}
UPDATE:
The problem of this is that one has alyways go back to the root in order to generate full sentences. So I guess the question is: How to remember the node which was already fully visited (this means where all children nodes were already explored)?
Printing all paths from the root to every leaf would mean to print the entire tree so I'd just use a simple DFS and do the following for each node:
add it to the list/stack
if the node has children, repeat for the children
if the node is a leaf, print the list/stack
pop the node from the list/stack
Example:
A
/ \
B E
/ \ / \
C D F G
The first steps would look like this:
put A on the list -> {A}
put B on the list -> {A,B}
put C on the list -> {A,B,C}
since C is a leaf, print the list (A,B,C)
remove C from the list -> {A,B}
put D on the list -> {A,B,D}
since D is a leaf, print the list (A,B,D)
...
if you know that the graph is indeed a tree (there is only one path to each node), them yes, a simple DFS would be more efficient (at least from a memory usage point of view). Otherwise, you can also use the iterative deepening DFS.
So here's a sample approach. Note that you need an extra visited field in your node structure:
public class TreeNodeExtra {
int val;
TreeNodeExtra left;
TreeNodeExtra right;
boolean visited;
TreeNodeExtra (int v) {
val = v;
visited = false;
}
}
private ArrayList<ArrayList<TreeNodeExtra>> all_path_from_root_to_leaf(TreeNodeExtra root) {
Stack<TreeNodeExtra> st = new Stack<>();
ArrayList<ArrayList<TreeNodeExtra>> res = new ArrayList<>();
st.push(root);
root.visited = true;
while (!st.isEmpty()) {
TreeNodeExtra top = st.peek();
if (top.left != null && !top.left.visited) {
st.push(top.left);
top.left.visited = true;
}
// if left node is null
else {
if (top.right == null && top.left == null) {
// we have a leaf
ArrayList<TreeNodeExtra> tmpList = new ArrayList<>();
for (TreeNodeExtra t : st) {
tmpList.add(t);
}
res.add(tmpList);
st.pop();
}
else if (top.right != null && !top.right.visited) {
st.push(top.right);
top.right.visited = true;
}
else {
st.pop();
}
}
}
return res;
}
A slight modification of DFS (which includes back-tracking) prints all the paths from a given source. In the below example the graph is represented in adjacency list format.
public void mDFS(ArrayList<node> v,int ind,ArrayList<Boolean> visit,ArrayList<node> tillNow){
visit.set(ind,true);
node n = v.get(ind);
int len = n.adj.size();
tillNow.add(n);
int count = 0;
for(node tmp: n.adj){
if( !visit.get(tmp.id) ){
count++;
tmp.pre = ind;
mDFS(v,tmp.id,visit,tillNow); // id gives index of node in v
}
}
if(count == 0){
for(node tmp: tillNow){
System.out.print((tmp.id + 1) + " - ");
}System.out.print("\n");
}
visit.set(ind,false);
tillNow.remove(tillNow.size() - 1);
return;
}