Suppose I have a list of nodes which represent a nested set hierachy (examples are in pseudo c#).
class Node
{
public decimal left;
public decimal right;
public decimal id;
public void AddChild(Node child) {...}
...
}
List<Node> nodes = GetFlatNodesWithoutChildrenSetFromDatabase();
The fields left, right and id get filled, since these values are stored in some database.
What is an efficient way to transform this flat list into a hierachy, that means filling in the appropriate children nodes for each parent node?
One way is just to find all ancestors of each node, sort them to find the parent node and add the child node to that node.
foreach (var n in nodes)
{
var parent = nodes.Where(i => i.left < n.left && i.right > n.right).OrderBy(i => i.right - n.right).FirstOrDefault();
if (parent != null)
parent.AddChild(n);
}
But this is rather inefficient.
Is there a better (that means faster) approach?
EDIT
Possible solution (as suggested by Chris):
var stack = new Stack<Node>(nodes.Take(1));
foreach (var n in nodes.Skip(1))
{
while (stack.Peek().right < n.left)
stack.Pop();
stack.Peek().addChild(n);
stack.Push(n);
}
Nodes have to be ordered by left.
The method I might think about exploring is to order by left and then you can just iterate through once.
You "open" a node when you get to its left and stick it on a stack.
When you get to a new node to process you check if the node on the top of the stack should be closed by determining if its right is less than the new nodes left. If it is you remove it from the stack (closing it) and you have processed all its children. You then do the check for the new top of the stack til you find one that is still open. You then add the current node as a child to the node on the top of the stack and that node is then opened (so it goes on the top of the stack).
The diagram on the wikipedia page you linked (http://en.wikipedia.org/wiki/Nested_set_model) is what inspired me to this.
My algorithm basically travels down the line in the middle and whenever you enter one of the sets is what I refer to as opening and leaving a set is closing. Clearly the most recent set you have opened but not closed will be on the top of the stack and thus where you put the children.
I think the complexity of this should be O(nlogn) due to the sort. The rest of it is just O(n).
I know that the question is quite old (I didn't find any other question/information on the topic) and I don't know "pseudo C#", but just in case some of you straggle with a recursive algorithm for nested sets list => tree algorithm, here is what I came to (in scala):
def retrieveUserFolderTree(user: User): Future[List[Folder]] = {
// Get a list of user's folders orderred by left asc
val dbFoldersPromise = folderDAO.findUserFolders(user)
dbFoldersPromise.map {
case rootFolder :: tail => generateChildren(0, rootFolder.right, tail)
case Nil => Nil
}
}
private def generateChildren(currentLeft: Int, currentRight: Int, dbFolders: Seq[DBFolder]): List[Folder] = {
dbFolders match {
case dbFolder :: tail if dbFolder.left > currentRight => Nil
case dbFolder :: tail if dbFolder.left > currentLeft => Folder(dbFolder.id, dbFolder.name, generateChildren(dbFolder.left, dbFolder.right, tail)) :: generateChildren(dbFolder.right, currentRight, tail)
case dbFolder :: tail => generateChildren(currentLeft, currentRight, tail)
case Nil => Nil
}
}
Hope this will help someone.
Maybe I missed a step somewhere but when I was working on this using the logic above I ended up with a couple elements on the stack that were duplicated. They were in the tree as expected but additionally they were also on the top of the stack above the root node. I had to add a little loop at the end to clean up the stack.
var stack = new Stack<DvrNode>(nodes.Take(1));
foreach (var n in nodes.Skip(1))
{
while (stack.Peek().Right < n.Left)
stack.Pop();
((List<DvrNode>)stack.Peek().Children).Add(n);
stack.Push(n);
}
while (stack.Peek().Left != 1)
stack.Pop();
Related
I'm creating a matching puzzle game, and I'm stuck in creating logic for this function.
Node is a class that has 3 parameters:
{
int a;
int b;
int c;
}
then if I have 2 node objects, say n1 and n2 and
(n1 == n2) if (n1.a == n2.a || n1.b == n2.b || n1.c == n2.c)
so if:
n1.a=6, n1.b=4, n1.c=3
and:
n2.a=4, n2.b=4, n2.c=5.
here ( n1 == n2 ) or n1 connects with n2 because ( n1.b == n2.b ).
The problem: I need to write logic for the function that accepts an array of node objects, and it should return a node object that can connect with all the nodes in the array. If a connecting node is impossible, it should return a null value. So the node returned should have at least 1 parameter in common with every object of the array.
I'm using ActionScript 3 but just need the logic part in either AS3 or pseudo-code.
You need to have a set of possible points that satisfy this condition, and filter it out at each new point added to the list. First you will have to spawn many "any-any" points, these must be differentiated from normal. You start the algorithm with one "any,any,any" point, then whenever a point (a,b,c) is added, you check the list of existing points, and drop any that are not compliant with "a,b,c", and a point with "any" is now axis-locked to either of the axes, meaning the first step makes "a,any,any","any,b,any","any,any,c" set of points in the list. This continues until either all the list is processed, or there are no points left in the list.
function allconnected(nodes:Vector.<Node>):Node {
var list:Array=[];
list.push({a:null,b:null,c:null}); // "any,any,any" initial object
for (var i:int=nodes.length-1;i>=0;i--) {
var node:Node=nodes[i]; // current node
if (list.length==0) return null; // no nodes match
for (var j:int=list.length-1;j>=0;j--) {
var o:Object=list.splice(j,1)[0]; // get the element out of the array
var pushed:Boolean=false;
if (o.a!==null) if (!pushed && (o.a==node.a)) {
list.push(o);
pushed=true;
}
if (o.b!==null) if (!pushed && (o.b==node.b)) {
list.push(o);
pushed=true;
}
if (o.c!==null) if (!pushed && (o.c==node.c)) {
list.push(o);
pushed=true;
}
// if this point connects by either side, and the side is defined, push it back
if (o.a===null) list.push({a:node.a,b:o.b,c:o.c});
if (o.b===null) list.push({a:o.a,b:node.b,c:o.c});
if (o.c===null) list.push({a:o.a,b:o.b,c:node.c});
// and if any side is "any", push an axis-aligned object in the list
} // this way new object that are aligned with current node
// are put into the array in an already processed segment, so we won't hit
// an infinite loop
}
// okay if we are here, then there is something left in the array
var result:Node=new Node();
result.a=list[0].a; // 0 if null, this is pretty much OK
result.b=list[0].b;
result.c=list[0].c;
return result;
}
This code has been written on-the-fly, and there might be errors inside, so don't blindly copy and paste, please.
Given two binary search trees, print the nodes in ascending order with time complexity O(n) and space complexity: O(1)
The trees cannot be modified. Only traversal is allowed.
The problem I am facing is with the O(1)space solution. Had there not been this constraint, it could have been easily solved.
The only way this can be done in space O(1) is if the nodes know their parent.
Otherwise you cannot even traverse the tree unless there is some additional aid.
However with this constraint it's again easy and back to tree-traversal, but without recursion. The tricky part is probably knowing which tree-path you came from when you go from a node to its parent (p) and cannot store this information as this would require O(log N) space.
However, you know the last value you outputted. If it is smaller than the one of p, go the right, otherwise go to p’s parent.
if we're talking about BST's as defined by wikipedia:
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 the additional perk that every node knows his parent, then the following C code does the trick (I hope you like C, I have put quite some effort in these 300 lines of demo application :D)
http://pastebin.com/MiTGqakq
(note that I didn't use recursion, because recursion is technically never O(1)space. The reason for this that every function call uses copies of the passed parameters, thus allocating additional space, making O_space dependent on the number of calls -> not in O(1)space.)
EDIT: ok, fixed version is linked. have fun.
I have solution of this problem.
I have coded my solution in C#, because it is my strongest language, but I hope that you will catch a main idea. Let's suppose, that each tree node has 3 references: to left, right and parent nodes.
So we have BinaryTree. How could we print it? Obviously:
this._tree.Print();
That wasn't very difficult. But how could we build Print method, if we should avoid recursion (because the last one involves O(log(n)) memory)? Have you ever read about lazy lists (or streams)? Lazy list doesn't hold the whole list in memory, but knows how to calculate next item based on current item. In every moment lazy list allocates O(1) memory. So, suppose we have managed to describe lazy list for tree. Then Print method is very simple:
public static void Print<T>(this BinaryTree<T> tree)
where T : IComparable<T>
{
var node = new TreeNodeWalker<T>(tree.Root, WalkerState.FromParent);
while (node != null)
{
node = node.WalkNext();
}
}
During this code snippet you could find out one unfamiliar entity: TreeNodeWalker. This object holds tree node that should be walked, state that signals in what moment of traversing this walker was created and method which gives next walker. In short walker performs next actions:
If we drop in any subtree from parent node, we should walk left subtree.
If we emerges from left subtree, we should print node value and walk right subtree.
If we emerges from right subtree we should walk parent.
It could be represented in code in the next way:
public class TreeNodeWalker<T>
where T:IComparable<T>
{
// Tree node, for which walker is created.
private readonly BinaryTreeNode<T> _node;
// State of walker.
private readonly WalkerState _state;
public TreeNodeWalker(BinaryTreeNode<T> node, WalkerState state)
{
this._node = node;
this._state = state;
}
public TreeNodeWalker<T> WalkNext()
{
if (this._state == WalkerState.FromParent)
{
// If we come to this node from parent
// we should walk left subtree first.
if (this._node.Left != null)
{
return new TreeNodeWalker<T>(this._node.Left, WalkerState.FromParent);
}
else
{
// If left subtree doesn't exist - return this node but with changed state (as if we have already walked left subtree).
return new TreeNodeWalker<T>(this._node, WalkerState.FromLeftSubTree);
}
}
else if (this._state == WalkerState.FromLeftSubTree)
{
// If we have returned from left subtree - current node is smallest in the tree
// so we should print it.
Console.WriteLine(this._node.Data.ToString());
// And walk right subtree...
if (this._node.Right != null)
{
//... if it exists
return new TreeNodeWalker<T>(this._node.Right, WalkerState.FromParent);
}
else
{
// ... or return current node as if we have returned from right subtree.
return new TreeNodeWalker<T>(this._node, WalkerState.FromRightSubTree);
}
}
else if (this._state == WalkerState.FromRightSubTree)
{
// If we have returned from right subtree, then we should move up.
if (this._node.Parent != null)
{
// If parent exists - we compare current node with left parent's node
// in order to say parent's walker which state is correct.
return new TreeNodeWalker<T>(this._node.Parent, this._node.Parent.Left == this._node ? WalkerState.FromLeftSubTree : WalkerState.FromRightSubTree);
}
else
{
// If there is no parent... Hooray, we have achieved root, which means end of walk.
return null;
}
}
else
{
return null;
}
}
}
You could see a lot of memory allocation in code and make decision that O(1) memory requirement is not fulfilled. But after getting next walker item, we don't need previous one any more. If you are coding in C++ don't forget to free memory. Alternatively, you could avoid new walker instance allocation at all with changing internal state and node variables instead (you should always return this reference in corresponding places).
As for time complexity - it's O(n). Actually O(3*n), because we visit each node three times maximum.
Good luck.
I'm having a hell of a time trying to figure this one out. Everywhere I look, I seem to be only running into explanations on how to actually traverse through the list non-recursively (the part I actually understand). Can anyone out there hammer in how exactly I can go through the list initially and find the actual predecessor/successor nodes so I can flag them in the node class? I need to be able to create a simple Binary Search Tree and go through the list and reroute the null links to the predecessor/successor. I've had some luck with a solution somewhat like the following:
thread(node n, node p) {
if (n.left !=null)
thread (n.left, n);
if (n.right !=null) {
thread (n.right, p);
}
n.right = p;
}
From your description, I'll assume you have a node with a structure looking something like:
Node {
left
right
}
... and that you have a binary tree of these set up using the left and right, and that you want to re-assign values to left and right such that it creates a doublely-linked-list from a depth first traversal of the tree.
The root (no pun intended) problem with what you've got so far is that the "node p" (short for previous?) that is passed during the traversal needs to be independent of where in the tree you currently are - it always needs to contain the previously visited node. To do that, each time thread is run it needs to reference the same "previous" variable. I've done some Python-ish pseudo code with one C-ism - if you're not familiar, '&' means "reference to" (or "ref" in C#), and '*' means "dereference and give me the object it is pointing to".
Node lastVisited
thread(root, &lastVisisted)
function thread(node, lastVisitedRef)
if (node.left)
thread(node.left, lastVisitedRef)
if (node.right)
thread(node.right, lastVisitedRef)
// visit this node, reassigning left and right
if (*lastVisitedRef)
node.right = *lastVisitedRef
(*lastVisitedRef).left = node
// update reference lastVisited
lastVisitedRef = &node
If you were going to implement this in C, you'd actually need a double pointer to hold the reference, but the idea is the same - you need to persist the location of the "last visited node" during the entire traversal.
I am required to print out(visit) the nodes on a single level of a binary tree.
I don't see how this can be done but then again I not very skilled with algorithms in general.
I know that in Breadth-First traversal you use a queue and that you start by putting the root node in the queue then you dequeue it visit it and enqueue it's children and then you dequeue the first enqued child visit it and enqueue it's children and so on...
And by my understanding this makes it impossible to know exactly when one level ends and another begins unless you assign each node it's level when the binary tree is created and then just check the level when you are doing the Breadth-First traversal.
Something like this(the code is in PHP but this is not a PHP related question it is a general algorithm related question - this is part of a function that adds a node to a binary tree storing the level in the node when each node is added):
if($this->root == null)
{
$this->root = $node;
$this->root->level = 1;
return;
}
$nextnode = $this->root;
$level = 1;
while (true)
{
if($node->value > $nextnode->value)
{
if($nextnode->right != null)
{
$nextnode = $nextnode->right;
$level++;
}
else
{
$nextnode->right = $node;
$nextnode->right->level = ++$level;
return;
}
}
else if($node->value < $nextnode->value)
{
if($nextnode->left != null)
{
$nextnode = $nextnode->left;
$level++;
}
else
{
$nextnode->left = $node;
$nextnode->left->level = ++$level;
return;
}
}
else if($node->value == $nextnode->value)
return;
}
So my questions are:
Is this the only way of printing the nodes on a single level of a binary tree?
Is there another way?
Is there another way without storing the level when creating the tree?
Would a recursive solution suite you?
I wrote this in C, i hope this is not a problem for you.
void traverse_tree_rec(TreeNode *ptn, int current_level, int targeted_level, (void*)(pVisit)(TreeElement*)){
if (ptn==NULL)
return;
else if(current_level == targeted_level)
pVisit(ptn->entry);
else{
traverse_tree_rec(ptn->left, current_level+1, targeted_level, pVisit);
traverse_tree_rec(ptn->right, current_level+1, targeted_level, pVisit);
}
}
void traverse_level(Tree *pTree, int level, (void*)(pFunction)(TreeElement)){
traverse_level_rec(pTree->root, 0, level, pFunction);
}
#Para,
this makes it impossible to know exactly when one level ends and
another begins unless ....
You need not traverse the whole tree during the BFS traversal you are trying to do.
You can modify the BFS psedocode given in wiki by introducing an array level[];
You have to do these:
initialize level as 0 for each node.
whenever u mark o in line: o ← G.opposite(t,e) assign level[o] = level[t]+1;
after t ← Q.dequeue() if level[t] > targeted_level break;
“Find a recurring element in a linked list of unicode characters. If a unicode character/s is found to have a duplicate then just delete that repeating node and adjust the list. The constraint was to not to use any extra memory.”
My answer:
Assuming that the unicode char doesn't include surrogate pair char As I am using c#
I don't know how can you find a duplicate character unless you know the values of the previous nodes while traversing the list, and to maintain the previous values you will need extra memory (hash table).
Guys, can you think of any solution to this question? It's an interview question on one of the sites. Also is it possible to solve this in O(n) time?
Here is my Implementation. Can You give feedback on it so that I can make it better?
public static void RemoveDup(Node head)
{
Node current1 = head;
Node current2;
while (current1 != null)
{
current2 = current1;
while (current2 != null)
{
if (current2.Next!=null && current1.Data == current2.Next.Data)
{
Node temp = current2.Next.Next;
current2.Next = temp;
current2=current1;
continue;
}
current2 = current2.Next;
if (current2 == null)
break;
}
current1 = current1.Next;
if (current1 == null)
break;
}
}
For each element in the list, search the list for that element and delete it starting at that element's position until you're out of elements.
I'll leave implementation and other choices to you.
The only way I can see to do this without saving previously-seen values somehow would be to use nested loops. Outer loop is "traverse the whole list", inner loop is "traverse the whole list and delete copies of the item pointed at by the outer loop".
Sort the list - then all duplicates will be in a row. That will take O(nlogn) time. Of course that assumes that you can sort the list (maybe the order is important?) and that you can sort it inplace (no extra memory).