Recursive method for level order traversal - binary-tree

The levelOrder method needs to call itself recursively to perform level order traversal. I'm having trouble in how to add (this) to accumulator. This is what I have so far.
public class BinaryTreeNode<T> {
private BinaryTreeNode<T> left;
private BinaryTreeNode<T> right;
private T data;
public BinaryTreeNode() {
this(null, null, null);
}
public BinaryTreeNode(T theData) {
this(theData, null, null);
}
public BinaryTreeNode(T theData, BinaryTreeNode<T> leftChild,
BinaryTreeNode<T> rightChild) {
data = theData;
left = leftChild;
right = rightChild;
}
public void levelOrder(
SortedMap<Integer, List<BinaryTreeNode<T>>> accumulator, int depth) {
accumulator.put(depth, this);// add (this) to accumulator
if (left != null) {
left.levelOrder(accumulator, depth);// if (left) is not null invoke
// this method for left
}
if (right != null) {
right.levelOrder(accumulator, depth);// do the same for (right)
}
}
}

UAB CS 302? Ok here's how I did it:
You have to check to see whether or not the accumulator contains a key at the current depth of (this) node.
Two possibilities:
a.) The accumulator does not contain a key that represents the depth of this node, so you have to create a new list of binary tree nodes and add it to the accumulator.
b.) The accumulator already has a key that represents the depth of this node, so you have to retrieve the list of binary tree nodes already there, and add this particular node to that list.
Also, if the left and right nodes are not null, then you want to recursively call this method at (depth+1) since they are lower on the tree than the current node.

Related

Java Stream collect all children

I would like to write a Java 8 stream().collect function that return a List<T> containing all children and subchildren of a node within a hierarchical structure. For example TreeItem<T> getChildren() and all of the children's children and so on, reducing it to a single list.
By the way, here is my final solution as generic method. Very effective and very useful.
public static <T> Stream<T> treeStream(T root, boolean includeRoot, Function<T, Stream<? extends T>> nextChildren)
{
Stream<T> stream = nextChildren.apply(root).flatMap(child -> treeStream(child, true, nextChildren));
return includeRoot ? Stream.concat(Stream.ofNullable(root), stream) : stream;
}
You have to flatten the tree using a recursive function. You have an example here: http://squirrel.pl/blog/2015/03/04/walking-recursive-data-structures-using-java-8-streams/
In order not to fall with stack overflow there is a way to replace stack with queue in heap.
This solution creates stream from iterator that lazily navigates tree holding next items in Queue.
Depending on type of queue traversal can be depth first or breadth first
class TreeItem {
Collection<TreeItem> children = new ArrayList<>();
}
Stream<TreeItem> flatten(TreeItem root) {
Iterator<TreeItem> iterator = new Iterator<TreeItem>() {
Queue<TreeItem> queue = new LinkedList<>(Collections.singleton(root)); //breadth first
// Queue<TreeItem> queue = Collections.asLifoQueue(new LinkedList<>(Collections.singleton(root))); //depth first
#Override public boolean hasNext() {
return !queue.isEmpty();
}
#Override public TreeItem next() {
TreeItem next = queue.poll();
queue.addAll(next.children);
return next;
}
};
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
}

Sentinel node in Binary Search Trees

I was wondering if in a way to avoid having to deal with the root as a special case in a Binary Search Tree I could use some sort of sentinel root node?
public void insert(int value) {
if (root == null) {
root = new Node(value);
++size;
} else {
Node node = root;
while (true) {
if (value < node.value) {
if (node.left == null) {
node.left = new Node(value);
++size;
return;
} else {
node = node.left;
}
} else if (value > node.value) {
if (node.right == null) {
node.right = new Node(value);
++size;
return;
} else {
node = node.right;
}
} else return;
}
}
}
For instance, in the insert() operation I have to treat the root node in a special way. In the delete() operation the same will happen, in fact, it will be way worse.
I've thought a bit regarding the issue but I couldn't come with any good solution. Is it because it is simply not possible or am I missing something?
The null node itself is the sentinel, but instead of using null, you can use an instance of a Node with a special flag (or a special subclass), which is effectively the null node. A Nil node makes sense, as that is actually a valid tree: empty!
And by using recursion you can get rid of the extra checks and new Node littered all over (which is what I presume is really bothering you).
Something like this:
class Node {
private Value v;
private boolean is_nil;
private Node left;
private Node right;
public void insert(Value v) {
if (this.is_nil) {
this.left = new Node(); // Nil node
this.right = new Node(); // Nil node
this.v = v;
this.is_nil = false;
return;
}
if (v > this.v) {
this.right.insert(v);
} else {
this.left.insert(v);
}
}
}
class Tree {
private Node root;
public Tree() {
root = new Node(); // Nil Node.
}
public void insert(Value v) {
root.insert(v);
}
}
If you don't want to use recursion, your while(true) is kind of a code smell.
Say we keep it as null, we can perhaps refactor it as.
public void insert(Value v) {
prev = null;
current = this.root;
boolean left_child = false;
while (current != null) {
prev = current;
if (v > current.v) {
current = current.right;
left_child = false;
} else {
current = current.left;
left_child = true;
}
}
current = new Node(v);
if (prev == null) {
this.root = current;
return;
}
if (left_child) {
prev.left = current;
} else {
prev.right = current;
}
}
The root will always be a special case. The root is the entry point to the binary search tree.
Inserting a sentinel root node means that you will have a root node that is built at the same time as the tree. Furthermore, the sentinel as you mean it will just decrease the balance of the tree (the BST will always be at the right/left of its root node).
The only way that pops in my mind to not manage the root node as a special case during insert/delete is to add empty leaf nodes. In this way you never have an empty tree, but instead a tree with an empty node.
During insert() you just replace the empty leaf node with a non-empty node and two new empty leafs (left and right).
During delete(), as a last step (if such operation is implemented as in here) you just empty the node (it becomes an empty leaf) and trim its existing leafs.
Keep in mind that if you implement it this way you will have more space occupied by empty leaf nodes than by nodes with meaningful data. So, this implementation has sense only if space is not an issue.
The code would look something like this:
public class BST {
private Node root;
public BST(){
root = new Node();
}
public void insert(int elem){
root.insert(elem);
}
public void delete(int elem){
root.delete(elem);
}
}
public class Node{
private static final int EMPTY_VALUE = /* your empty value */;
private int element;
private Node parent;
private Node left;
private Node right;
public Node(){
this(EMPTY_VALUE, null, null, null);
}
public Node(int elem, Node p, Node l, Node r){
element = elem;
parent = p;
left = l;
right = r;
}
public void insert(int elem){
Node thisNode = this;
// this cycle goes on until an empty node is found
while(thisNode.element != EMPTY_VALUE){
// follow the correct path for the insertion here
}
// insert new element here
// thisNode is an empty node at this point
thisNode.element = elem;
thisNode.left = new Node();
thisNode.right = new Node();
thisNode.left.parent = thisNode;
thisNode.right.parent = thisNode;
}
public void delete(int elem){
// manage delete here
}
}

Why do I need the visited state in Breadth First Search?

I've implemented a breadth first search algorithm (actually, it's breadth first traversal because I'm not searching for any particular node, simply printing out the node values in the order they are visited) and haven't used any state tracking of each node - i.e. I haven't marked any node as visited. In most BFS implementations I see this notion of marking a node as visited so that you never visit it twice, but in my implementation I can't see any case where this would be possible.
Could someone explain why the visited state is ever useful and/or necessary?
Here's my implementation:
import java.util.LinkedList;
import java.util.Queue;
public class BFS {
public static void printTree(Node root) {
Queue<Node> queue = new LinkedList<Node>();
queue.add(root);
while(queue.isEmpty() == false) {
Node curr = queue.remove();
System.out.println(curr.getValue());
if (curr.getLeft() != null) {
queue.add(curr.getLeft());
}
if (curr.getRight() != null) {
queue.add(curr.getRight());
}
}
}
public static void main(String[] args) {
Node leaf1 = new Node(5);
Node leaf2 = new Node(6);
Node leaf3 = new Node(7);
Node leaf4 = new Node(7);
Node leaf5 = new Node(11);
Node rightRightRoot = new Node(12, leaf4, leaf5);
Node leftRoot = new Node(1, leaf1, leaf2);
Node rightRoot = new Node(9, leaf3, rightRightRoot);
Node root = new Node(4, leftRoot, rightRoot);
printTree(root);
}
static class Node {
private int value;
private Node left, right;
public Node(int value, Node left, Node right) {
this.value = value;
this.left = left;
this.right = right;
}
public Node(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public Node getLeft() {
return left;
}
public Node getRight() {
return right;
}
}
}
Most BFS implementations you`ve seen traverse arbitrary graphs and you travel through the tree. The difference in those two cases are cycles. Arbitrary graph can have them and states are necessary for not putting the node into the queue twice, but in your case you may live without them.
Your code makes reference to a tree. By definition, a tree can't have cycles, so you are right that you don’t need to track if vertices have been visited if you are traversing a tree. A graph can have cycles, so it enables multiple vertices to be legitimate parents of a vertex.
For example, with a graph of four vertices (A,B,C,D) and the following topology:
A
/ \
B C
\ /
D
If a breadth-first search is started from A, both B & C can reach D. During execution, both B & C will add D to the queue, and thus it will be visited and printed twice.
The following code will print 4 twice:
Node D = new Node(4);
Node C = new Node(3, D, null);
Node B = new Node(2, null, D);
Node A = new Node(1, B, C);
printTree(A);

how to connect circular doubly-linked lists

Consider, I have given 2 items of the circular doubly-linked lists A and B. I want to implement a function which connects both of the lists.
This task is simple. However, I want to handle the case where A and B are the members of the same linked list. In this case it would just do nothing. Is it possible to implement it in O(1)? Do I need to check whether A and B are from the same list first? Or can I somehow magically swap/mix the pointers?
IMO it is not possible, but I'm unable to prove it.
thanks
You can. Being curious myself, I sketched an implementation in Java. Assuming a linked list as follows
public class CLinkedList {
class Node {
Node prev, next;
int val;
public Node(int v) {
val = v;
}
}
Node s;
public CLinkedList(Node node) {
s = node;
}
void traverse() {
if (s == null)
return;
Node n = s;
do {
System.out.println(n.val);
n = n.next;
} while (n != s);
}
...
}
a merging method would look like
void join(CLinkedList list) {
Node prev = list.s.prev;
Node sprev = s.prev;
prev.next = s;
sprev.next = list.s;
s.prev = prev;
list.s.prev = sprev;
}
which works just fine when the lists are different.
If they're not, all this does is just split the original list into two perfectly valid, different linked lists. All you should do is just join them again.
Edit: The join method joins (lol) two lists if they are different or (contrary to its name) splits the list if the nodes belong to the same list. Applying join twice thus has no effect, indeed. But you can make use of this property in other ways. The method below works fine:
public void merge(CLinkedList list) {
CLinkedList nList = new CLinkedList(s.next);
join(nList);
nList.join(list);
join(nList);
}
public static void main(String[] args) {
CLinkedList list = new CLinkedList(new int[] {1,2,3});
CLinkedList nlist = new CLinkedList(list.s.next);
list.merge(nlist);
list.traverse();
}
Still O(1) :) Keeping the small disclaimer - not the best quality code, but you get the picture.

Is it possible to design a tree where nodes have infinitely many children?

How can design a tree with lots (infinite number) of branches ?
Which data structure we should use to store child nodes ?
You can't actually store infinitely many children, since that won't fit into memory. However, you can store unboundedly many children - that is, you can make trees where each node can have any number of children with no fixed upper bound.
There are a few standard ways to do this. You could have each tree node store a list of all of its children (perhaps as a dynamic array or a linked list), which is often done with tries. For example, in C++, you might have something like this:
struct Node {
/* ... Data for the node goes here ... */
std::vector<Node*> children;
};
Alternatively, you could use the left-child/right-sibling representation, which represents a multiway tree as a binary tree. This is often used in priority queues like binomial heaps. For example:
struct Node {
/* ... data for the node ... */
Node* firstChild;
Node* nextSibling;
};
Hope this helps!
Yes! You can create a structure where children are materialized on demand (i.e. "lazy children"). In this case, the number of children can easily be functionally infinite.
Haskell is great for creating "functionally infinite" data structures, but since I don't know a whit of Haskell, here's a Python example instead:
class InfiniteTreeNode:
''' abstract base class for a tree node that has effectively infinite children '''
def __init__(self, data):
self.data = data
def getChild(self, n):
raise NotImplementedError
class PrimeSumNode(InfiniteTreeNode):
def getChild(self, n):
prime = getNthPrime(n) # hypothetical function to get the nth prime number
return PrimeSumNode(self.data + prime)
prime_root = PrimeSumNode(0)
print prime_root.getChild(3).getChild(4).data # would print 18: the 4th prime is 7 and the 5th prime is 11
Now, if you were to do a search of PrimeSumNode down to a depth of 2, you could find all the numbers that are sums of two primes (and if you can prove that this contains all even integers, you can win a big mathematical prize!).
Something like this
Node {
public String name;
Node n[];
}
Add nodes like so
public Node[] add_subnode(Node n[]) {
for (int i=0; i<n.length; i++) {
n[i] = new Node();
p("\n Enter name: ");
n[i].name = sc.next();
p("\n How many children for "+n[i].name+"?");
int children = sc.nextInt();
if (children > 0) {
Node x[] = new Node[children];
n[i].n = add_subnode(x);
}
}
return n;
}
Full working code:
class People {
private Scanner sc;
public People(Scanner sc) {
this.sc = sc;
}
public void main_thing() {
Node head = new Node();
head.name = "Head";
p("\n How many nodes do you want to add to Head: ");
int nodes = sc.nextInt();
head.n = new Node[nodes];
Node[] n = add_subnode(head.n);
print_nodes(head.n);
}
public Node[] add_subnode(Node n[]) {
for (int i=0; i<n.length; i++) {
n[i] = new Node();
p("\n Enter name: ");
n[i].name = sc.next();
p("\n How many children for "+n[i].name+"?");
int children = sc.nextInt();
if (children > 0) {
Node x[] = new Node[children];
n[i].n = add_subnode(x);
}
}
return n;
}
public void print_nodes(Node n[]) {
if (n!=null && n.length > 0) {
for (int i=0; i<n.length; i++) {
p("\n "+n[i].name);
print_nodes(n[i].n);
}
}
}
public static void p(String msg) {
System.out.print(msg);
}
}
class Node {
public String name;
Node n[];
}
I recommend you to use a Node class with a left child Node and right child Node and a parent Node.
public class Node
{
Node<T> parent;
Node<T> leftChild;
Node<T> rightChild;
T value;
Node(T val)
{
value = val;
leftChild = new Node<T>();
leftChild.parent = this;
rightChild = new Node<T>();
rightChild.parent = this;
}
You can set grand father and uncle and sibling like this.
Node<T> grandParent()
{
if(this.parent.parent != null)
{
return this.parent.parent;
}
else
return null;
}
Node<T> uncle()
{
if(this.grandParent() != null)
{
if(this.parent == this.grandParent().rightChild)
{
return this.grandParent().leftChild;
}
else
{
return this.grandParent().rightChild;
}
}
else
return null;
}
Node<T> sibling()
{
if(this.parent != null)
{
if(this == this.parent.rightChild)
{
return this.parent.leftChild;
}
else
{
return this.parent.rightChild;
}
}
else
return null;
}
And is impossible to have infinite child, at least you have infinite memory.
good luck !
Hope this will help you.

Resources