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
Related
Assume we have a tree of nodes (Huffman-tree) that hold string values in them. How would I go about traversing the tree and spitting out an index of a specific node if I had a tree like this? The numbers I drew inside the circles would be the index I want (especially 12 or 13).
Note: Due to miscommunication, I will repeat: the #'s I wrote inside the circles are not the values that the nodes hold. They are the index of that node. My problem was that I couldn't find the index, since the trees are structured weirdly - not a classic BST tree, and the values inside aren't numerical.
Edit: I redrew the image to make my question more clear.
Either way, I figured it out. I'll write up the answer after my finals.
The tree you are showing is not a binary search tree. The central property of a binary search tree that allows it to be searched efficiently is that the left descendants of a node are smaller, and the right descendants bigger than the node itself (in terms of the index value).
If you have a proper binary search tree, you can find a node with given index by comparing with nodes and following the corresponding branch, starting with the root.
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.
I've been working with Binary Search Trees in my spare time, and I want to be able to delete nodes from a tree.
In order to get this to work, I need to find the maximum value. How do you go about doing that? Pseudo-code or hints would be appreciated. I'm stuck and not exactly sure how to even begin this.
A binary search tree has the following properties:
The left subtree of a node contains only nodes with keys less than the node's key.
The right subtree of a node contains only nodes with keys greater than the node's key.
Both the left and right subtrees must also be binary search trees.
With that definition in mind, it should be very easy to find the max.
A simple pseudocode would be this. It it is indepandant to binary search I think.
int maxi = 0
foreach(array as item) // or any other loop
if item>maxi then maxi = item
Is the following list a BST or not?
list:{2,5,3,8,6}
Is there a way I can determine this?
Consider that my list will have 100000 elements.
Quick answer is: no. BST is a tree and you have a list.
Long answer is: it may be possible to encode a tree as a list, in which case, whether your list can be decoded into a tree or not will depend on the encoding algorithm. See BST wiki page for more details http://en.wikipedia.org/wiki/Binary_search_tree
In fact your list may be an encoded version of BST. If you read elements from left to right pushing them onto a stack, and whenever you stack has 3 elements do:
parent = pop()
right = pop()
left = pop()
push new Node(parent, left, right)
then you should get a valid BST. But I am only speculating here.
you are having a list , you need to construct BST from this list
A BST has following properties
1- Each node has two children or it is a leaf node
2- For each node its left subtree is smaller than node's value
3- For each node its right subtree is greater than node's value
a bst MUST BE BALANCED i.e. while inserting nodes in a BST , code must respect above 3 conditions.
Searching in a BST is O(log n) operation that is because , each search step divide the search space into two halfs and choose one of the half.
There is a case where search will take O(N) time
Consider following
node = {1,2,3,4,5}
if we make the BST from this node set it will be right alifned that means every next node will be on the right subtree , here if we want to search for a item , we need to traverse whole right sub tree like a link list.
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.