I saw the following post order traversal algorithm in some website... it seems to be correct. I just want to verify that this algorithm works correctly — is this algorithm correct for post order traversal without recursion?
void postOrderTraversal(Tree *root)
{
node * previous = null;
node * s = null;
push(root);
while( stack is not empty )
{
s = pop();
if(s->right == null and s->left == null)
{
previous = s;
process s;
}
else
{
if(s->right == previous or s->left == previous)
{
previous = s;
process s;
}
else
{
push( s );
if(s->right) { push(s->right); }
if(s->left) { push(s->left); }
}
}
}
}
Try to write iterative versions of pre-order, in-order, and post-order binary traversal methods. You will then see the pattern or methodology of converting their corresponding recursive versions into the iterative versions.
Key point is sticking to some basic rules:
- Use node selection (e.g., currentNode = currentNode->Left before reiterating the loop, etc.) for immediate node traversal.
- Use stack to remember nodes that need to be visited or revisited later.
- If a node need to be "REvisited," detecting / keeping the state so that you can indicate whether the next node needs to be "processed" in next iteration or one of more of the child nodes should be visited before the node can be processed.
If you stick to these rules, you can esily accomplish the tasks.
Here is an example of the iterative post-order traversal. Ignore BinarySearchTree - it works for any binary trees.
public static IEnumerator<BinarySearchTreeNode<T>> GetPostOrderTraverseEnumerator(BinarySearchTreeNode<T> root)
{
if (root == null)
{
throw new ArgumentNullException("root");
}
Stack<BinarySearchTreeNode<T>> stack = new Stack<BinarySearchTreeNode<T>>();
BinarySearchTreeNode<T> currentNode = root;
// If the following flag is false, we need to visit the child nodes first
// before we process the node.
bool processNode = false;
while (true)
{
// See if we need to visit child nodes first
if (processNode != true)
{
if (currentNode.Left != null)
{
// Remember to visit the current node later
stack.Push(currentNode);
if (currentNode.Right != null)
{
// Remember to visit the right child node later
stack.Push(currentNode.Right);
}
// Visit the left child
currentNode = currentNode.Left;
continue;
}
else if (currentNode.Right != null)
{
// Remember to visit the current node later
stack.Push(currentNode);
// Visit the right child
currentNode = currentNode.Right;
continue;
}
}
// Process current node
yield return currentNode;
// See if we are done.
if (stack.Count == 0)
{
break;
}
// Get next node to visit from the stack
BinarySearchTreeNode<T> previousNode = currentNode;
currentNode = stack.Pop();
// See if the next node should be processed or not
// This can be determined by the fact that either of the current node's child nodes
// has just been processed now.
processNode = (previousNode == currentNode.Left || previousNode == currentNode.Right);
}
}
no here prev should not start with null
eg:for bst having nodes 5 2 1 3 7 6 8 0
it will not consider zero because at 1 its right is null and this time previous will also be null hence it will not consider its left child i.e. 0
write previous=any value but not null
Here is the working code
Stack s=new Stack();
while(true){
if(root!=null){
s.push(root);
root=root.left;
}
else{
if(s.top().right==NULL){
root=s.top();
s.pop();
System.out.println(root.data);
if(root==s.top().right){
System.out.println(s.top().data);
s.pop();
}
}
if(!s.empty())
root=s.top().right;
else
root=NULL;
}
}
Related
I have such a class for implementation of Sorted Linked List in C#. Now it's not actually sorted, but what changes do I have to make to this method it become one?
class LinkedSortedList<T>
{
public Node<T> Head { get; set; }
public Node<T> Tail { get; set; }
public int Count { get; set; }
public LinkedSortedList()
{
Head = null;
Tail = null;
Count = 0;
}
public LinkedSortedList(T data)
{
CreateList(data);
}
public void AddElement(T data)
{
if (Tail != null)
{
var node = new Node<T>(data);
Tail.Next = node;
Tail = node;
Count++;
}
else
{
CreateList(data);
}
}
public void CreateList(T data)
{
var node = new Node<T>(data);
Head = node;
Tail = node;
Count = 1;
}
I want to modify AddElement function so that the list is and remains sorted. How can I implement this logic?
A key observation you need to make in order to complete the task is that at the beginning of AddElement the list is either empty, or sorted. If the list is empty, your task is trivial; if the list is sorted, you must pick an insertion point for the element being added, and insert the new element there. The list will remain sorted after the insertion, because no other elements would need to be moved.
To find the insertion point, start walking the list from the head until you either (1) find an element that is greater than the one being inserted, or (2) you reach the end of the list. In both cases you simply insert the new element immediately after the last element that you've passed during the traversal, or at the head if the initial element is greater than the one you are inserting.
Currently you're just adding elements to the end of the list. Instead, we want to walk the list and look at each value until we find the correct place to insert the node.
One way to do this is to do the following checks:
Is the Head null? If so, create a new list with this data and we're done.
Is the new node's data less than the Head data? If so, put this node in front of the Head and point the Head to our new node.
Is the new node's data greater than the Tail data? If so, put this node after the Tail and point the Tail to our new node.
Otherwise, create a "current" node that points to the head, compare the data of the current node with our new node, and continue to move through the list by setting "current" to it's Next property until we find the proper place to insert the new node. Then rearrange the Next and Previous properties of the three nodes (the new node, the one before it, and the one after it).
For example:
public void AddElement(T data)
{
if (Head == null)
{
CreateList(data);
}
else
{
var node = new Node<T>(data);
if (node.Data < Head.Data)
{
Head.Previous = node;
node.Next = Head;
Head = node;
}
else if (node.Data > Tail.Data)
{
Tail.Next = node;
node.Previous = Tail;
Tail = node;
}
else
{
var current = Head;
while(node.Data >= current.Data && current.Next != null)
{
current = current.Next;
}
node.Previous = current.Previous;
if (node.Previous != null) node.Previous.Next = node;
current.Previous = node;
node.Next = current;
if (Head == current) Head = node;
Count++;
}
}
}
I'm trying to search a TreeView for a particular string, once I have found the index of the node, I wish to return its index and change the back color of that particular node, however my current code does not seem to be returning any matches, unless it's the root node:
private void ApplyRulesetColors()
{
foreach (var rule in dictOverwriteEntries)
{
int iResultIndex = SearchTreeView(rule.Key, tvDirectoryStructure.Nodes);
if (iResultIndex > -1)
{
switch (rule.Value)
{
case Operations.Overwrite:
tvDirectoryStructure.Nodes[iResultIndex].BackColor = Color.Red;
break;
case Operations.Delete:
break;
case Operations.None:
break;
default:
break;
}
}
}
}
This is the function that should be searching the treeview:
private int SearchTreeView(string p_sSearchTerm, TreeNodeCollection p_Nodes)
{
foreach (TreeNode node in p_Nodes)
{
if (node.Text == p_sSearchTerm)
{
return node.Index;
}
if (node.Nodes.Count > 0)
SearchTreeView(p_sSearchTerm, node.Nodes);
}
return -1;
}
At the moment that will only ever match on the root node value and return 0, even though (as far as I can tell) it should be searching through the entire tree including child nodes.
Thank you.
There are two problems in your code:
You don't return the result of the recursive call, but -1 if the node was not found in the root node's children.
You return the nodes Index, which is the index in the node's parent children collection, not a global index.
I suggest to return the TreeNode itself instead. Change your method like that:
private TreeNode SearchTreeView(string p_sSearchTerm, TreeNodeCollection p_Nodes)
{
foreach (TreeNode node in p_Nodes)
{
if (node.Text == p_sSearchTerm)
return node;
if (node.Nodes.Count > 0)
{
TreeNode child = SearchTreeView(p_sSearchTerm, node.Nodes);
if (child != null) return child;
}
}
return null;
}
And use it like that:
private void ApplyRulesetColors()
{
foreach (var rule in dictOverwriteEntries)
{
TreeNode resultNode = SearchTreeView(rule.Key, tvDirectoryStructure.Nodes);
if (resultNode != null)
{
switch (rule.Value)
{
case Operations.Overwrite:
resultNode.BackColor = Color.Red;
break;
case Operations.Delete:
break;
case Operations.None:
break;
default:
break;
}
}
}
}
Note however that this code will only find the first matching node. I don't know if your tree may contain multiple nodes with the same Text. In that case you should use another property to identify the node.
You need to return TreeNode itself not it's index, as the index is relative to the parent of located node. Also, your recursive SearchTreeView doesn't return an element when it found it during recursive call. The code below will work and return TreeNode itself, which you can style as you wish.
You may wish to know that your approach is not efficient, as you need to iterate the tree as many times as you have rules in your list. It may be more efficient if you iterate the tree once, and then match rules for each node in the list. Your code may be a good case to apply Visitor pattern: http://www.dofactory.com/net/visitor-design-pattern
Any way, here is a correct SearchTreeView:
private TreeNode SearchTreeView(string p_sSearchTerm, TreeNodeCollection p_Nodes)
{
foreach (TreeNode node in p_Nodes)
{
if (node.Text == p_sSearchTerm)
{
return node;
}
if (node.Nodes.Count > 0)
{
var result = SearchTreeView(p_sSearchTerm, node.Nodes);
if (result != null)
{
return result;
}
}
}
return null;
}
I want to add an element to a linked list so that the list remains sorted. I wrote this function. He's got a place that should be included, but I do not know how to insert the element.
public void AddSorted(int num)
{
Node n = new Node(num);
Node curr = _first;
Node curr1 = _first.Link;
while (curr1.Data < n.Data && curr1 != null)
{
curr = curr.link;
curr1= curr1.link;
}
// how to add element ???
}
You have provided absolutely no context regarding your LinkedList class, so I can only make an educated guess.
Given what I understand from the above code, after traversing to the location you want to insert the new Node, you will need to set the link of Node curr1 (which is the last Node) to the new node object.
Node temp = curr1.Link; // store next Node in temporary object
curr1.Link = n; // Insert new Node
Remember that you need to set the link of the new node to the next node in the LinkedList in order to continue the LinkedList (if the newly inserted Node is not the last):
n.Link = temp;
Please let me know if I made a mistake understanding your code, I can then change my answer accordingly.
With the help of my dear friends.
I could write this function.
Below you can see the code :
public void AddSorted(int num)
{
Node n = new Node(num);
Node curr = _first;
if (_first == null || _first.Data >= n.Data)
{
n.Link = _first;
_first = n;
}
else
{
while (curr.Link != null && curr.Link.Data < n.Data)
{
curr = curr.Link;
}
n.Link = curr.Link;
curr.Link = n;
}
I have a binary tree written in c# with nodes defined with IComparable data. It all works just fine in the sense that I can populate the tree with any data type I like (although I've only tried populating it with a single type of data at a time) and perform functions like finding the depth, in-order searching, counting leaves, etc.
I'm trying to write a function to find a data value in the tree using a recursive algorithm. The algorithm finds the data, but then does not stop when the data is found. There is one exception -- when the data is in the root node. I can't figure out where it is going wrong. The function reports that it found the data, at which point it is supposed to return that node and quit, but it keeps going looking in the children nodes.
Thanks to the accepted answer, here is the working code I have:
private TreeNode findValueStartingAtNode(TreeNode node, IComparable value)
{
if (node == null)
{
return null;
}
int test = value.CompareTo(node.data);
if (test < 0)
{
return findValueStartingAtNode(node.left_child, value);
}
else if (test > 0)
{
return findValueStartingAtNode(node.right_child, value);
}
else
{
return node;
}
}
Code:
public TreeNode findValue(IComparable value)
{
TreeNode node = findValueStartingAtNode(this.root, value);
if (node == null)
{
Console.WriteLine("value not found");
return null;
}
else
{
return findValueStartingAtNode(this.root, value);
}
}
private TreeNode findValueStartingAtNode(TreeNode node, IComparable value)
{
Console.WriteLine("looking for value {0}", value);
if (node == null)
{
Console.WriteLine("node is null -- returning null");
return null;
}
else if (value.CompareTo(node.data) == 0)
{
Console.WriteLine("value found at current node");
Console.WriteLine("current node data is {0}", node.data);
Console.WriteLine("done and returning node");
return node;
}
else
{
Console.WriteLine("checking children");
TreeNode left = findValueStartingAtNode(node.left_child, value);
TreeNode right = findValueStartingAtNode(node.right_child, value);
Console.WriteLine("the values are left: {0}, right: {1}", left.data, right.data);
if (value.CompareTo(left.data) == 0)
{
Console.WriteLine("value found in left child");
return left;
}
else if (value.CompareTo(right.data) == 0)
{
Console.WriteLine("value found in right child");
return right;
}
else
{
Console.WriteLine("value not found in either child");
Console.WriteLine("current node data is {0}", node.data);
return null;
}
}
}
Output:
C:\Users\abalter\Documents\CS273\TreeNode\TreeNode\bin\Debug>TreeNode.exe
looking for value 50
value found at current node
current node data is 50
done and returning node
looking for value 50
value found at current node
current node data is 50
done and returning node
(in main) value 50 found
looking for value 45
checking children
looking for value 45
value found at current node
current node data is 45
done and returning node
looking for value 45
checking children
looking for value 45
checking children
looking for value 45
node is null -- returning null
looking for value 45
checking children
looking for value 45
node is null -- returning null
looking for value 45
node is null -- returning null
Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
at TreeNode.BinaryTree.findValueStartingAtNode(TreeNode node, IComparable value) in c:\Users\abalter\Documents\CS273\TreeNode\TreeNode\BinaryTree.cs:line 220
at TreeNode.BinaryTree.findValueStartingAtNode(TreeNode node, IComparable value) in c:\Users\abalter\Documents\CS273\TreeNode\TreeNode\BinaryTree.cs:line 218
at TreeNode.BinaryTree.findValueStartingAtNode(TreeNode node, IComparable value) in c:\Users\abalter\Documents\CS273\TreeNode\TreeNode\BinaryTree.cs:line 217
at TreeNode.BinaryTree.findValueStartingAtNode(TreeNode node, IComparable value) in c:\Users\abalter\Documents\CS273\TreeNode\TreeNode\BinaryTree.cs:line 218
at TreeNode.BinaryTree.findValue(IComparable value) in c:\Users\abalter\Documents\CS273\TreeNode\TreeNode\BinaryTree.cs:line 186
at TreeNode.Program.Main(String[] args) in c:\Users\abalter\Documents\CS273\TreeNode\TreeNode\Program.cs:line 36
C:\Users\abalter\Documents\CS273\TreeNode\TreeNode\bin\Debug>
A Binary Search Tree has certain properties. The property that's important here is that for each node, everything in that node's left subtree is smaller than the node's value and everything in its right subtree is larger (according to the comparer).
You only ever have to look in one subtree. Use that property to find the item you're looking for:
private TreeNode findValueStartingAtNode(TreeNode node, IComparable value)
{
if (node == null) return null;
int comp = value.CompareTo(node.data);
if (comp == 0) return node; //Found it
if (comp < 0) return findValueStartingAtNode(node.left_child, value); //The item must be in the left subtree
return findValueStartingAtNode(node.right_child, value); // The item must be in the right subtree
}
Bonus: instead of a recursive method, here's an iterative Search function from my own implementation: (It's also generic)
private BinaryTreeNode<T> Search(BinaryTreeNode<T> node, T item)
{
if (node == null) return null;
int c;
while (node != null && (c = comparer.Compare(item, node.Value)) != 0)
node = c < 0 ? node.Left : node.Right;
return node;
}
Instead of looking down the left and right, then checking to see if it was found you should look down the left only. If it is found there, return that, otherwise look down the right. If it is there, return that, otherwise return null. Your else would look something like this:
Console.WriteLine("checking children");
TreeNode left = findValueStartingAtNode(node.left_child, value);
if (left != null && value.CompareTo(left.data) == 0)
{
Console.WriteLine("value found in left child");
return left;
}
else
{
TreeNode right = findValueStartingAtNode(node.right_child, value);
if (right != null && value.CompareTo(right.data) == 0)
{
Console.WriteLine("value found in right child");
return right;
}
else
{
Console.WriteLine("value not found in either child");
Console.WriteLine("current node data is {0}", node.data);
return null;
}
}
findValueStartingAtNode should be returning either null if the value isn't found or the correct TreeNode if the value is found. There's no reason to do a comparison of the values of the right and left child nodes, because the recursive call on the children nodes will check the value of the children on its own. It will also fail and throw a NullReferenceException whenever a node is encountered without both children. Lastly, your findValue call is searching the tree twice.
I would replace your code with this:
public TreeNode findValue(IComparable value)
{
TreeNode node = findValueStartingAtNode(this.root, value);
if (node == null)
{
Console.WriteLine("value not found");
}
return node;
}
private TreeNode findValueStartingAtNode(TreeNode node, IComparable value)
{
Console.WriteLine("looking for value {0}", value);
if (node == null)
{
Console.WriteLine("node is null -- returning null");
return null;
}
else if (value.CompareTo(node.data) == 0)
{
Console.WriteLine("value found at current node");
Console.WriteLine("current node data is {0}", node.data);
Console.WriteLine("done and returning node");
return node;
}
else
{
Console.WriteLine("checking left child");
TreeNode left = findValueStartingAtNode(node.left_child, value);
if(left != null) return left;
Console.WriteLine("checking right child");
TreeNode right = findValueStartingAtNode(node.right_child, value);
if(right != null) return right;
Console.WriteLine("value not found in either child");
Console.WriteLine("current node data is {0}", node.data);
return null;
}
}
It should also be mentioned that this doesn't qualify as a binary search tree. It will perform a depth-first search, ending only when the value is found or the entire tree has been visited.
That seems...complicated to me, what with the double calls and all.
It's important to note that every node of a tree is itself a tree. There's no difference between the root node of the tree and any other node of the tree. You just have to do the walk once. Like many recursive problems, the tree walk has two cases:
The special case: The tree is empty (null).
The general case: The tree is non-empty.
Consequently, the tree walk logic is this:
The Special Case. If the root (current) node is null, the search failed. return null.
The General Case. Compare the root (current) node's payload to the desired value.
EQUAL: A Hit! Return the root (current) node.
LESS THAN: A miss. Return the results of visiting the left child.
GREATER THAN: A miss. Return the results visiting the right child.
That's all there is to it. Given a node structure like this:
public class TreeNode<T> where T:IComparable
{
public TreeNode<T> Left { get ; set ; }
public TreeNode<T> Right { get ; set ; }
public T Payload { get ; set ; }
}
The tree search code shouldn't be much more difficult than this
public TreeNode<T> FindNodeWithValue( IComparable value )
{
Func<IComparable,int> compareToDesiredValue = (x) => x.CompareTo(value) ;
TreeNode<T> node = FindNodeWithValue( this.Root , compareToDesiredValue ) ;
return node ;
}
private TreeNode<T> FindNodeWithValue( TreeNode<T> root , Func<IComparable,int> compareToDesiredValue )
{
TreeNode<T> result = null ;
if ( root != null )
{
int cc = compareToDesiredValue( root.Payload ) ;
switch ( cc )
{
case 0 : result = root ; break ;
case -1 : result = FindNodeWithValue( root.Left , compareToDesiredValue ) ; break ;
case +1 : result = FindNodeWithValue( root.Right , compareToDesiredValue ) ; break ;
default : throw new InvalidOperationException() ;
}
}
return result ;
}
Further, given that this search is directed, so you've got no need to keep track of parent nodes and no need to be able to backtrack on alternatives, the code can easily be iterative and as simple as this:
public TreeNode<T> FindNodeWithValue( IComparable value )
{
TreeNode<T> current = this.Root ;
int cc ;
while ( current != null && 0 != (cc=current.Payload.CompareTo(value)) )
{
// if we land here, current node does not have our desired value.
// follow the appropriate left or right child.
current = cc < 0 ? current.Left : current.Right ;
}
// once the while loop completes, current holds the result, with
// null indicating failure and non-null being the subtree containing
// the desired value as its root.
return current ;
}
public void Insert(int value)
{
if (value < Data)
{
if (LeftNode == null)
{
LeftNode = new TreeNode(value);
}
else
{
LeftNode.Insert(value);
}
}
else if (value > Data)
{
if (RightNode == null)
{
RightNode = new TreeNode(value);
}
else
{
RightNode.Insert(value);
}
}
}
I wrote method to add element in BST recursively, It checks for value to add less than or greater than and add it in its proper place, but I want to know how iterative method works? I need iterative add method for my BST.
Ok, here's an iterative version of your algorithm:
public void Insert(int value)
{
TreeNode current = this;
while (current != null)
{
if(current.Data < value)
if(current.LeftNode == null)
{ current.LeftNode = new TreeNode(value); break; }
else current = current.LeftNode;
else
if(current.RightNode == null)
{ current.RightNode = new TreeNode(value); break; }
else current = current.RightNode;
}
}
You can find a implementation in Java at wikipedia, what is very similar C# http://en.wikipedia.org/wiki/Binary_search_tree
We start at root:
Node root = m_root;
while (root != null) {
then look if the value is less os greater than root.
if (data < root.getData()) {
Now we know if we need to traverse at left or right. The logic at left and right are the same. We look if the slot is empty and if it is, we put the value at that slot.
if (root.getLeft() == null) {
root.setLeft(new TreeNode(data, null, null));
return;
}
If the slot contains a value, then we set that slot as root and continue the process.
} else {
root = root.getLeft();
}
An iterative method is one that will repeat.
Iterative method implies it will be called repeatedly.
Recursion implies the method will call itself n times, where n > 0.
Searching a binary search tree is done using a method which calls itself (recursive) until it finds the end of a branch.
To do an insert, a search is executed to find the correct place to place the node.