Is it possible to convert a linked list to binary search tree BST.
and also have a link between them in a way of the current element, is pointing to the same in both linked list and BST
linked list :
3 , 5 ,6 ,1, 2 ,0,4
BST :
3
/ \
1 5
/ \ / \
0 2 4 6
when current of the binary search tree points to 1
it should also point to 1 in the linked list
Absolutely, you can use the same nodes in both data structures. The nodes would then each have the two links of their "linked-list-ness" and the two children of their "BST-ness".
So as a quick example, a node might have fields like this:
class Node {
public Node next, prev; // for the linked list
public Node left, right; // for the BST
// put some data in here too
}
It takes some care to use those nodes, because it's easy to get the two data structures "out of sync", for example if you remove a node from one but forget to remove it from the other. Then again, maybe that's what you want. But other things stay the same, for example if you do rotations in the BST then you don't have to touch the linked-lists fields at all, and similarly if you swap two nodes in the linked-list then the BST fields are not affected at all. So in those cases the code will be the same as it would have been if you had a normal kind of node that is part of only one data structure.
Of course this trick does not apply to the standard library implementations.
You can absolutely have that as harold pointed out above. And as he also points out, you can get them out of sync if your implementation has bugs that allow the data structures to go out of sync.
So, you could do this instead:
//YourBST.java
public class YourBST<T> {
public List<T> toList() { //Convert this to a list }
}
//YourList.java
public class YourList<T> {
public YourBST<T> toBST() { //... }
}
And then, when modifying one or the other..just call the conversion methods to set the other datastructure.
YourBST<String> bst = new YourBST<String>();
YourList<String> list = new YourList<String>();
modify(bst); //modify your BST in some way
list = bst.toList();
modify(list); //modify your List in some way
bst = list.toBST();
Edit: if you indeed want the same object to have prev/next references as well as left/right references, that still requires the node class as Harold described above. This solution simply fixes the "out of sync" problem.
Related
Can someone show me the basic structure of a 2,3,4 balanced search tree node in Java? I am not sure how to represent a 3 key node. Should I use an array of size three? Or should I have a left entry (entry=key +value object), middle entry and right entry fields?
And how does the left child and right child work out? In a binary search tree the left and right childs are for a node. In a 2,3,4 tree, the left and right child seem to be for each key. So should a 2,3,4 tree node itself be an object that holds 3 binary tree nodes, instead of holding 3 entries?
The "traditional OO" option of having separate classes for the 4 node variants (0 for leaf, 2, 3 or 4 children otherwise) is awkward, because references to the node would then have to be updated, leading to having to store a back reference to the parent and updating the parent every time the number of children changed.
Instead, it seems far more simple and performant to break the "state affecting behaviour rather than subclass" anti-pattern and use LinkedLists for both the values and the child nodes:
public class Node<T> {
LinkedList<Node<T>> children = new LinkedList<>();
LinkedList<T> values = new LinkedList<>();
public Node(T value) {
values.add(value); // there is always a value
}
// other methods to find, insert, delete, etc
}
Using a LinkedList gives you constant time (ie O(1) time complexity) on all operations (although n=4 is small, still every bit helps), the ability to iterate without an iterator via next(), which is needed to iterator conveniently over both lists simultaneously, and a more convenient API for balancing operations.
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'm having a really difficult time solving this problem. I have spent hours on it and can't figure it out.
I have a linked list that I am trying to manually sort. My nodes are called CNodes. There is a start CNode, a tail CNode and a newNext CNode.
Each Node contains a contact. The contact has a firstname that I am trying to sort the list by.
I know there are more automatic ways to do this, but I need to demonstrate that I understand how to sort (which clearly I do not at this point).
I am trying to do this by iterating over each node and comparing it to start, then changing the start entity if it qualifies.
This code is not working...I've been working on it for two days and am really stuck.
Any specific suggestions would be really appreciated.
CNode nextNode=start;
while(nextNode.getNext()!=null) {
CNode newNext;
tail=nextNode;
while(tail!=null) {
if(start.getContact().getStrFirstName().compareTo(tail.getContact().getStrFirstName()) > 0) {
//We put the starting node in a temp node
newNext=start;
newNext.setNext(tail.getNext());
//We set our current node to the start
start=tail;
start.setNext(newNext);
//Set the next node of start to the original next one of the one we
//just removed from the chain
//Set current marker to the new first nodes' next entity
tail=start.getNext();
//Set the next node for the marker to the one we just removed
} else {
tail=tail.getNext();
}
}
nextNode=nextNode.getNext();
}
The best thing you can do is start with an array, and get the sorting concept down. You also need to figure out what type of sort you are going to do, you're currently trying to do a bubble sort. There is also a merge sort, quick sort, and others. Once you pick the type of sort you want, you can then do it on an array, then move to node.
Here are some sorts:
https://github.com/BlaineOmega/MergeSort Bubble sort:
http://en.wikipedia.org/wiki/Bubble_sort Quick sort:
http://en.wikipedia.org/wiki/Quicksort
So what you're doing is a bubble sort. For a visual representation of what the is, look at this (from Wikipedia): http://upload.wikimedia.org/wikipedia/commons/c/c8/Bubble-sort-example-300px.gif
So in the while loop, when two nodes need to be switched, we're going to store the 'next' (current) node into a temp, put the tail in the next node, and put the temp into the tail, like a triangle.
temp
/ ^
/ \
V \
tail -- next
I attempted to rewrite your code, but was confused as to if start is you're root node, and if not, what is you're root node. If it is, it should be only used once, and that is declaring you're tail node.
Good luck, hope I helped,
Stefano
I have a binary tree that looks like this
the object that represents it looks like this (java)
public class node {
private String value = "";
private TreeNode aChild;
private TreeNode bChild;
....
}
I want to read the data and build the tree from a string.
So I wrote some small method to serialize it and I have it like this
(parent-left-right)
0,null,O#1,left,A#2,left,C#3,left,D#4,left,E#4,right,F#1,right,B#
Then I read it and I have it as a list - objects in this order O,A,C,D,E,F,B
And now my question is - how to I build the tree?
iterating and putting it on a stack, queue ?
should I serialize on a different order ?
(basically I want to learn the best practices for building a tree from string data)
can you refer me to a link on that subject ?
Given your second string representation, there is no way to retrieve the original tree. So unless any tree with that sequence is acceptable, you'll have to include mor information in your string. One possible way would be representing null references in some fashion. Another would be using parentheses or similar.
Given your first representation, restoring the data is still possible. One algorithm expliting the level information would be the following:
Maintain a reference x to the current position in your tree
For every node n you want to add, move that reference x up in your tree as long as the level of x is no less than the level of n
Check that now the level of x is exactly one less than the level of n
Make x the parent of n, and n the next child of x
Move x to now point at n
This works if you have parent links in your nodes. If you don't, then you can maintain a list of the most recent node for every level. x would then correspond to the last element of that list, and moving x up the tree would mean removing the last element from the list. The level of x would be the length of the list.
Your serialization is not well explained, especially regarding how you represent missing nodes. There are several ways, such as representing the tree structure with ()s or by using the binary tree in an array technique. Both of these can be serialized easily. Take a look at Efficient Array Storage for Binary Tree for further explanations.
This question already has answers here:
Finding the intersecting node from two intersecting linked lists
(6 answers)
Closed 9 years ago.
MergePoint (LinkList list1, LinkList list2){
p = list1.head;
q = list2.head;
while (p.next!=null && q.next!=null){
if (p.next == q.next){
System.out.print(p.value + " is the Merging node");
return;
}
p=p.next;
q=q.next;
}
}
I'm trying to solve a problem to find out the merging node of 2 linked lists.
Before looking at other solutions, I decided to write my code and then compare to the other existing solutions.
The approach ive taken here is to find the common node that both the list pointers are pointing to.
Do you agree with this code or is there something im missing here?
Three solutions come to mind.
First, the nested loop Irfy posted. It uses constant memory but O(N*M) time, where N and M are the lengths of the two lists.
Second, you can trade space for time, by putting every node of one list into a HashSet first, then walking the other list and doing lookups into the HashSet. Because that lookup is O(1), the total time is O(N+M) (building the hashtable and walking the other list). However, the trade-off is O(N) space required for the table.
Third, if you're allowed to modify the data at least temporarily, you can make one of the lists circular (by connecting the next pointer of its last node to the first) and then use the algorithms described by Stepanov in Elements of Programming to solve the problem in O(N+M) time and O(1) space, because you know that one of the lists is now circular, whereas the other is P-shaped: it starts with its own part and eventually hits the circle of the other list. The place where it hits is called the connection point, and Stepanov gives you an algorithm to find it. Finally, you just unhook the last node again.
The algorithms in question are actually available in the sample chapter, which you can download here:
http://www.elementsofprogramming.com/book.html
Your code will only work for the special class of cases where the merging node is in the same position in both the lists. I don't think there's an easy, sub-O(n^2) way to do this -- in other words, you'll need to compare every node of one list, with every next of second list, and vice versa.
MergePoint (LinkList list1, LinkList list2) {
p = list1.head;
while (p != null) {
q = list2.head;
while (q != null) {
if (p == q){
System.out.print(p.value + " is the Merging node");
return;
}
q = q.next;
}
p = p.next;
}
}
This will only work if the "merging nodes" are at the same position in the list.
For example, let's say you have two linked lists...
List 1 has 5 nodes (nodes A, B, C, D, E)
List 2 has 6 nodes (nodes V, W, X, Y, C, D)
Obviously the common node is C. What you seem to be looking for in your code is the node that points to the common node (don't know if it really has a name, merging node is as good as anything,) so in this case you are looking for A and Y.
Your code will do something like this:
A.next == V.next? no
B.next == W.next? no
C.next == X.next? no
and so on and so forth. This is in the format [Element from List 1 compared with Element from List 2]
What you really want to do is compare the first element of List 1 with all the elements of List 2. Then, if you don't find it, compare the second element of List 1 with all the elements of list 2, and continue to do this so on and so forth.
Since this sounds like a homework question, I won't give you the answer (but I will give you a hint: you will probably need nested loops,) but if you have any further questions with implementing it, then ask away.
Also, may want to look at a special case for the head node, in case the first node in either list is the common node. In this case, you're only comparing the "next" node, meaning the very first one won't ever match if it is the common node between any of the two lists.