How to create a Binary Tree from a General Tree? - java

I have to solve the following constructor for a BinaryTree class in java:
BinaryTree(GeneralTree<T> aTree)
This method should create a BinaryTree (bt) from a General Tree (gt) as follows:
Every Vertex from gt will be represented as a leaf in bt.
If gt is a leaf, then bt will be a leaf with the same value as gt
If gt is not a leaf, then bt will be constructed as an empty root, a left subTree (lt) and a right subTree (lr). Lt is a stric binary tree created from the oldest subtree of gt (the left-most subtree) and lr is a stric binary tree created from gt without its left-most subtree.
The frist part is trivial enough, but the second one is giving me some trouble. I've gotten this far:
public BinaryTree(GeneralTree<T> aTree){
if (aTree.isLeaf()){
root= new BinaryNode<T>(aTree.getRootData());
}else{
root= new BinaryNode<T>(null); // empty root
LinkedList<GeneralTree<T>> childs = aTree.getChilds(); // Childs of the GT are implemented as a LinkedList of SubTrees
child.begin(); //start iteration trough list
BinaryTree<T> lt = new BinaryTree<T>(childs.element(0)); // first element = left-most child
this.addLeftChild(lt);
aTree.DeleteChild(hijos.elemento(0));
BinaryTree<T> lr = new BinaryTree<T>(aTree);
this.addRightChild(lr);
}
}
Is this the right way? If not, can you think of a better way to solve this? This solution, for example, gives me a bunch of nodes with no data at all, I don't know if this is an issue of the problem itself or mine.
Thank you!

The problem is that most trees cannot be validly reduced to a binary tree.
Reading your comment you are fully aware of that.
Taking for example a tree with a root node with 3 children. There is no direct way to make a binary tree out of this without sacrificing connectivity. That's where those empty nodes come from. With them, the structure of the general tree is preserved. You can reconstruct it, deleting the empty nodes and reassembling the tree from the two subtrees.
I have not debugged your code. If it does what you said it would do, it is a good solution. Empty nodes sort of store the connectivity information of the general tree. They are allowed to be there.

There is another, widely known, way to make a binary tree from a general tree, with no "connectivity nodes".
This method can be best understood like this:
Node{ Node{
data; data;
first_child; => left;
next_sibling; right;
} }
This basically represents the list of children of the general tree as a linked list, with the addition of each node having a reference to the linked list of it's children. As you can see, this is structurally equivalent to a binary tree.
So, in pseudocode (with edge cases omitted for simplicity)
BinaryTree(gtree){
root=BinaryNode(gtree.data,BinaryNode(gtree.children),null);
}
BinaryNode(List<gnode> sibs){
BinaryNode(sibs.first.data,BinaryNode(sibs.first.children),BinaryTree(sibs.rest));
}
BinaryNode(data,left,right){
data=data;
left=left;
right=right;
}
Of course, if you need to have the structure you described, this will be useless, but in general, this is a fairly good way to create a binary tree from a general tree.

Related

StackOverFlow Error when converting 1,000,000 Nodes in a Splay Tree to a SinglyLinkedList

I have implemented a Splay Tree class that uses nodes to store data. In this class I have tried to convert the data of nodes into a Singly Linked List. 1,000,000 nodes can be inserted into the splay tree and it works perfectly. Using recursion I get a StackOverFlow error when the tree contains 1,000,000 nodes. However when the tree contains around 15000 nodes it is able to be converted to a linked list without a problem.
Here is the code for my toList Method that is inside the splay tree class
public LinkedList<Node> toList() {
LinkedList<Node> list = new LinkedList<Node>();
Node node = root;
addToList(node, list);
return list;
}
private void addToList(Node node, LinkedList<Node> list) {
if(node != null) {
addToList(node.left, list);
list.add(node);
addToList(node.right, list);
}
}
I used this test class below to test the function of this method
#Test
public void testConversionToLinkedList {
SplayTree<Integer,String> st = new SplayTree<Integer,String>();
for(int i = 0; i < 1000000; i++) {
st.insert(i, Integer.toString(i));
}
assertEquals(1000000, st.size());
LinkedList<Node> list = st.toList();
assertEquals(1000000, list.size());
}
The test passes when the size entered is around 15000, however any number greater than that will show a StackOverFlowError
The error occurs at the line addToList(node.left, list);
This is really weird because when i used the same recursion technique to print the data of the nodes into a txt file, there is no StackOverFlow error and the data prints perfectly.
I have tried to use In Order Traversal, PreOrder and PostOrder but I still receive the same error at 1,000,000 nodes. I do know that it could be doing recursion too deeply and the stack runs out of memory. If that is the case is there any way I can convert a splay tree of nodes into a linked list?
Any idea what could be going wrong? cheers
Your poblem is the recursive algorithm. As you figured out there is a limit in the stack size, which is build when you have recursion.
You can always transform recursion to a loop.
here are some examples for DFS and BFS algorithms using loops: Non recursive Depth first search algorithm
You can increase the stack’s size. To do it you have to pass parameter to the jvm.
The format is -Xss[g|G|m|M|k|K].
For example: java -Xss4m YourTreeProgram
The root issue is that splay trees can have a height equal to their node count, so the recursive algorithms you often see applied to binary trees are risky when applied to splay trees.
The easiest approach is to splay the tree as you go.
Find the tree's minimum node. Simply follow the "left" links from the root all the way until they are null. Splay this node to the root, then add it to your list.
Find its successor. I.e. follow the root's "right" link once, then follow "left" repeatedly until null. Splay that node to the root, then add it to your list.
Repeat step 2 until there is no successor (i.e. the root's "right" link is null).
Finding the minimum and successor nodes are no different from other kinds of trees.

Removing a node from a binary search tree in Java

I've implemented a binary search tree with nodes (represented as users) but I'm having trouble getting my deFriend() method to work. This method should delete a node from the tree whilst keeping the "rules" of a binary search tree - e.g. root bigger than left sub-tree, but smaller than right sub-tree.
I understand that when deleting a node from a binary search tree, I should consider 3 cases:
1 - when the node to delete has no children,
2 - when the node to delete has one child,
3 - when the node to delete has two children. can't figure this one out
My deFriend() method works for the first two cases but not for the last one. I even know what node I need to replace it with if it's the third case but I can't get it down with code. I can conceptualize it or draw it on paper, but I can't translate that to code. I've included links to the two classes that I think are necessary to fixing my problem. I'm convinced my problem lies between lines 111 and 114 of my BinaryTree class. Thanks in advance.
User class: https://gist.github.com/anonymous/732f02628f6edf622d88363b68cf22ee
BinaryTree class: https://gist.github.com/anonymous/1be7b5577c959dc1bcf6c77474b11bce
When removing a node from a binary search tree it is mandatory to maintain the in-order sequence of the nodes. There are three possible cases to consider:
if node has no children simply remove the node from the tree.
if node has one child remove the node and replace it with its child.
if node D has two children do not delete it. Instead, choose either its in-order predecessor node or its in-order successor node as replacement node E. Copy the user values of E to D. If E does not have a child simply remove E from its previous parent. If E has a child, say F, it is a right child. Replace E with F at E's parent.

leaf to root bst traversal

I was just wondering, given a node which points to its left and right children, is it possible to somehow get an inorder print of the whole bst tree?
All i know about the tree is that it is BST.
And all I know about the node is that he knows who his children are (left and right).
I don't have access to neither the root nor the father of the node.
The node chosen is picked randomly, and I need to return an inorder of the whole tree.
I think there is not enough info to get started at, and my friend got this question during a job interview, and was wondering if that was an unsolvable question or is there a trick I don't know about?
Thanks in advance for any help :)
The only thing you can do from this situation is to travel downwards, because you have no pointer to the parent node. The only case when you can print the whole tree is when the node considered is the root.
So, you can get the inorder print of the subtree rooted at the current node. If this node is the root, then it prints the whole tree. If it is not, then it does not.
Just in case, inorder print is simple:
def inorder(node):
if node == null: return
inorder(node.left)
print node.data
inorder(node.right)

How to evaluate the performance of a binary tree implemented via a linked list or an array list?

This falls under "a software algorithm" from https://stackoverflow.com/help/on-topic
This is from an interview question http://www.glassdoor.com/Interview/Yelp-Software-Engineering-Intern-Interview-Questions-EI_IE43314.0,4_KO5,32_IP2.htm,
particularly "performance of binary tree if implemented thru array or linkedlist"
How would you go about implementing a binary tree via an array or a linked list?
The way I was taught to do it was by having a linked node type of structure that has two pointers, left and right, that is (from https://courses.cs.washington.edu/courses/cse143/12wi/lectures/02-22/programs/IntTreeNode.java)
public class IntTreeNode {
public int data;
public IntTreeNode left;
public IntTreeNode right;
public IntTreeNode(int data) {
this(data, null, null);
}
public IntTreeNode(int data, IntTreeNode left, IntTreeNode right) {
this.data = data;
this.left = left;
this.right = right;
}
}
And then in the actual binary tree
public class IntTree {
IntTreeNode overallRoot;
public IntTree() {
overallRoot = null;
}
....
}
How would you go about this if you were just using an array or a linked list(one pointer)?
But anyways this is supposed to be a quick fire question. Even if you didn't implement the tree, which you aren't supposed to, how would you analyze the performance of the tree? Doesn't the performance depend on the state of the tree, like if it is a BST? Like for a BST, find would be O(log n) because you're cutting off half the tree each time.
How would you analyze performance based on these two implementations right away?
I'm not sure if I understood correctly, but this is what I thought of.
Basically, you can store the nodes in the tree as elements of an array/list.
For arrays, think of something like this:
public class Node {
public int data;
public int left;
public int right;
...
}
Your tree would be an array of Nodes (Node[] tree), such that the root would be the first element tree[0].
Every element refers to its left and right children as indices in the array.
For example, tree[ tree[0].left ] would be the left child of the root.
A left value of -1 could indicate that the node does not have a left child; similarly for right.
For example, consider the following tree:
5
/ \
2 8
\ / \
3 6 9
Suppose you have initially allocated 10 elements in your array.
Since you have fewer than 10 nodes in the tree, some of them will be null.
Here is what it could look like:
(I am representing each Node as a (data,left,right) tuple)
{ (5,1,2) , (2,-1,4) , (8,5,3) , (9,-1,-1) , (3,-1,-1) , (6,-1,-1) , null , null , null , null }
Thus for the node (8,5,3), you can tell that its left child is the sixth element (node (6,-1,-1)) and its right child is the fourth element (node (9,-1,-1)).
The performance of the insertion/deletion functions could vary depending on your precise implementation.
A similar idea can hold for linked lists (but remember that they do not have random access: finding the i-th element requires traversing the list, element by element).
Hope this helps.
When analyzing algorithms as such, you want to look at what type of binary tree is it (balanced vs. unbalanced), plus the three factors regarding sapce/time complexity:
Insertion
Deletion
Search
Comparing linked list vs. array implementations of binary trees, we see the following:
Linked lists insertions and deletions are much less expensive than when done in arrays (think of array element shifts you have to do to fulfill those two operations.
Linked lists offer flexible size, while arrays do not; you will have to handle array expansion when data does not fit within initial array size.
Arrays offer random access, while linked lists do not; e.g. when dealing with an array implementation of a full or complete binary tree, we can easily compute the indices of any node in the tree.
Having that said, for specific implementations of Binary Search Trees, linked lists are better implementations simply because in a binary search tree, access follows the rules of a binary search tree (root's value is greater than left child and less than right child). Therefore, for insertion/deletion and search, average complexity should be O(log n), provided the tree is balanced. If the binary search tree is not balanced, your complexity becomes O(n) for all operations - this is the worst case scenario.

Dealing with "Keys" in Binary Search Trees

Should I always, use some data as a key value while dealing with the Binary Search trees? I'm asking this becasue I would need key at some point of time
if I want to search an element in the tree. Is thre any other alternative?
For example, please consider the following code:
class Node {
int iData; // data used as key value
double fData; // other data
Node leftChild; // this node's left child
Node rightChild; // this node's right child
}
My Second Question:
Is there any way I can find elements in a Binary Tree as Binary Tree doesn't have any property just like Binary Search Tree where left node of parent must be less than the parent and right node must be greater.
I don't see why you always need a key. You can just use double fData as the value you use to determine which node is bigger / smaller (if your requirement suits).
I believe Binary Seach Tree is a Binary Tree where the elements are ordered. Hence nodes on a Binary Tree is not necessarily ordered. So yes you can still find elements on a Binary Tree -- but you have to scan the entire node. You lose the performance benefit of a BST

Categories

Resources