I'm taking an algorithm course at the university, and for one of my projects I want to implement a red-black tree in C# (the implementation itself isn't the project, yet just something i decided to choose to help me out).
My red-black tree should hold string keys, and the object i created for each node looks like this :
class sRbTreeNode
{
public sRbTreeNode Parent = null;
public sRbTreeNode Right = null;
public sRbTreeNode Left = null;
public String Color;
public String Key;
public sRbTreeNode()
{
}
public sRbTreeNode(String key)
{
Key = key;
}
}
I already added some basic methods for printing the tree, finding the root, min/max key (by alphabet), etc...
I'm having trouble inserting nodes (hence, building the tree).
Whoever's familiar with red-black trees knows that when adding a node to one side, you could have changed the balance of the tree.
To fix this, you need to "rotate" around nodes on the tree in order to balance the tree out.
I wrote a RightRotate and LeftRotate method in pseudo-code, and then when i tried to implement it in C#, i ran into a bunch of reference problems with the sRbTreeNode object i created.
This is the pseudo-code I wrote for the LeftRotate method :
LeftRotate(root, node)
y <- node.Right;
node.Right <- y.Left;
if (y.Left != null)
y.Left.Parent <- node;
y.Parent <- node.Parent;
if (node.Parent = null)
root <- y;
else
if (node = node.Parent.Left)
node.Parent.Left = y;
else
node.Parent.Right = y;
y.Left <- node;
node.Parent <- y
I received a suggestion to implement it straight forward, but without using the 'ref' keyword, which i tried at first.
This is how i did it :
public static void LeftRotate(sRbTreeNode root, sRbTreeNode node)
{
sRbTreeNode y = node.Right;
node.Right = y.Left;
if (y.Left != null)
y.Left.Parent = node;
y.Parent = node.Parent;
if (node.Parent == null)
root = y;
else
if (node == node.Parent.Left)
node.Parent.Left = y;
else
node.Parent.Right = y;
y.Left = node;
node.Parent = y;
}
Now, when i debug, i see that it works fine, but the objects i pass to this method are only rotated within the scope of the method. When it leaves this method, it seems like there was no change to the actual nodes. That is why i thought of using the 'ref' keywords in the first place.
What am i doing wrong ?
Because in the body of your method you do this:
root = y;
you need to pass root in with a ref modifier. node doesn't need one, becausenode itself is never updated to point at a different ndoe.
.
I don't see why you should have had any issues with references - the Left/Right/Parent nodes can be copied just as in this pseudo-code.
You should be able to expand it to C# without too much fuss - unless you're using the 'ref' keyword, in which case you could very well get unpredictable results.
Perhaps if you could show the code you've actually written thus far, and we can help debug that.
My recommendations:
Do not include parent pointers. They are not essential for the insertion or deletion algorithms and will make your code more complex. For example LeftRotate can be written with just one parameter and will be about half as long if you do not use parent pointers.
Use an enum for the Color property rather than a string, and initialise it in the constructor.
Read this article if you haven't already.
Related
So I'm trying to search through a binary tree filled with a Country object stored in the node as T Data. The Country object as has String variable containing the name of the country (countryName), I want to search in a textbox for the countryName and to return a boolean value. So it would traverse the binary tree of Country objects and match the value in the textbox field with the countryName. One could store the values of the object separately in the nodes but I'd rather use generic types. Below are my searching methods.
public Boolean Contains(T item)
{
return contains(item, ref root);
}
private Boolean contains(T item, ref Node<T> tree)
{
if (tree != null)
{
if (item.CompareTo(tree.Data)==0)
{
Console.WriteLine("Found");
return true;
}
return contains(item, ref tree.Left) || contains(item, ref tree.Right);
}
else
{
return false;
}
}
And the Node structure
public T Data;
public Node<T> Left;
public Node<T> Right;
public int balanceFactor;
public Node(T Data)
{
this.Data = Data;
Left = null;
Right = null;
}
Never call a function inside of itself, this will eventually cause a StackOverflowException. You should do something like this instead;
Depth First Search using Stack<T>
static bool Contains<T>(T item, Node<T> tree) {
Stack<Node<T>> stack = new Stack<Node<T>>();
stack.Push(tree); //Push the root node into the stack
Node<T> current;
do {
current = stack.Pop(); //Get the last item that was added to the stack and remove it at the same time
if (item.Equals(current.Data)) //If the item we just popped has its 'Data' property equal to the 'item'
{
Console.WriteLine("Found");
return true; //then return true
}
//Otherwise add the left and right nodes to the stack if they exist.
if(current.Left != null) stack.Push(current.Left);
if(current.Right != null) stack.Push(current.Right);
} while(stack.Count > 0); //If the stack still contains items, go back to the 'do'
//If we've reached this point we've searched the entire tree and found nothing
return false;
}
Dotnetfiddle usage example
When you execute a function in a program the program needs some way of storing where it was, this is called the stack. Stacks generally have a limited size of how large they can be, and if you reach this limit and you attempt to go one depth further it will throw a StackOverflowException.
Basically this is how your function looks in operation:
contains(contains(contains(contains(contains(contains(contains(contains(...
The amount of levels of depth it has to account for will not typically occur in an application unless you're doing something wrong like calling a function inside of itself, which is what you're doing.
So instead of making the stack go to crazy levels of depth, let's just keep a list of all of the stuff we need to compare to what we're searching, and along the way add their children to the same list.
This is where the Stack<T> type comes in. The Stack type, despite sharing a name with the stack of the program, are not the same thing. The Stack type is just a list of items that has the ability to add (Push(T)), as well as retrieve the last item that was added to the list while removing it from the list at the same time (Pop()).
So instead of going a level of depth down every time we want to search a node, we instead just add it to a Stack while looping it.
In binary search tree (BST) you must compare items in a way that gives you same sorting order (using same comparer) when you insert/search/delete an item. You can't use one comparer (for example, that compares countries population) in insert and than search country by name in the same BST in O(lg(N)).
In order to build BST that allows you to search country by name use either procedure argument like Func<of T, of T, of int> or very common in .NET Framework IComparer<of T> in tree constructor. See SortedSet<of T> class design and SortedSet<of T>(IComparer<of T>) constructor specifically.
Example implementation:
Node<T> _root;
readonly IComparer<T> _comparer;
public bool Contains(T target)
{
return Contains(_root, target);
}
bool Contains(Node<T> root, T target)
{
if (root == null)
return false;
int cmp = _comparer.Compare(target, root.Data);
if (cmp == 0)
return true;
return cmp < 0 ? Contains(root.Left, target) : Contains(root.Right, target);
}
Also note t in your BST search implementation it is crutial for performance to make recursive call only on a single subtree (left or right).
For more information check Binary search tree page on Wikipedia, SortedSet - custom order when storing a class object and Using lambda expression in place of IComparer argument discussions on StackOverflow.
I have a node class which is contained in a SortedDictionary:
SortedDictionary<Node, bool> openList = new SortedDictionary<Node, bool>();
I need to write the CompareTo method on the node, so that the nodes are sorted from lowest to highest based on an int value(F). I also need to be able to check if a node already exists in the dictionary based on their position (this position is what makes the node Unique). The CompareTo looks like this:
public int CompareTo(Node other)
{
if (GridPosition != other.GridPosition)
{
if (F > other.F)
{
return 1;
}
if (F < other.F)
{
return -1;
}
return -1;
}
return 0;
}
The problem is, that it doesn't always return the correct result. For example, the following line of code will return false even though the node is in the dictionary. However it sorts all the nodes that I add to the dictionary exactly as I want it.
Node node = new Node(); //It has a grid position and a f value
openList.add(node, false);
if(openList.Keys.Contains(node)) //this returns false
{
}
To fix this I created an EqualityComparer and used it while comparing the values. The equality comparer looks like this:
class NodeEqualityComparer : IEqualityComparer<Node>
{
public bool Equals(Node x, Node y)
{
return x.GridPosition == y.GridPosition;
}
public int GetHashCode(Node obj)
{
return obj.GridPosition.GetHashCode();
}
}
I'm using this equality comparer as a parameter in the Contains method on the SortedDictionary, this works fine and it returns the correct result based on the content in the Dictionary:
if (openList.Keys.Contains(currentNode,new NodeEqualityComparer())) //This will return true if the node is in the dictionary
{
}
The problem occours when I need to remove a node from the Dictionary. The remove function is using the CompareTo method on the Node to find the node to remove, and as I stated earlier, this function appreantly doesn't return the correct result when comparing the objects. This means that the code below will not remove the node from the dictionary 100% of the time. You can't pass an equalityComparer to the remove function, so that can't fix my problem.
Node node = new Node(); //It has a grid position and a f value
openList.add(node, false);
openList.Remove(node);
Maybe I'm handeling this in a wrong way, so if anyone have some suggestions for solving this problem I'll be very happy to hear them. Maybe I can write a CompareTo function that solves the problem?
This problem is probably a result of you comparing GridPosition in the comparer.
C# distinguishes between value types and reference types. If you compare two int variables the comparer will base equality on the value. For instantiated classes however the comparisson is based upon the reference, meaning you are comparing whether an object is the object in memory.
This:
if (GridPosition != other.GridPosition)
{
will probably almost always return true, thus resulting in your sort order being correct, because you are providing the order int he if statment nested inside:
if (F > other.F)
{
return 1;
}
if (F < other.F)
{
return -1;
}
If however (F == other.F) you assign -1, so the ContainsKey will not recognize these objects as equal.
Depending on what type GridPosition is, you should provide an appropriate comparer, for instance something like
if (GridPosition.X != other.GridPosition.X && GridPosition.Y != other.GridPosition.Y)
And depending on what F is, you are violating the mathematical principal of symmetry, as an object with different GridPosition and equal F will alway be sorted before any other object fulfilling this. Thus for two objects you could get A == B ==> -1 and B == A ==> -1 which isnt useful in any case.
So you would have to do this in the nested if:
if (GridPosition != other.GridPosition)
{
if (F > other.F)
{
return 1;
}
if (F < other.F)
{
return -1;
}
/////////////////////////////////
return 0;
/////////////////////////////////
}
or expand the comparission to a third condition beyond GridPosition and F
EDIT: Based on the information you provided in the comments, you don't actually want a dictionary in this case, just a list with proper sorting. For instance:
List<Node> myList = new List<Node>();
myList.Sort((node1, node2) => node1.F > node2.F);//Sort the list based on their node value
As for your bool; I don't know what this represents, but I'm under the strong impression that you want a regular Dictionary<Node, bool> for this. Then use the list myList to handle whatever node you need as next waypoint and lookup the bool corresponding to a node in the dictionary whenever you need it.
I've searched so long and hard for this and now I'm at road's end. I've had this issue with more than this project, but I ended up scrapping the others. I have a code (C#) which is basically me trying to do Huffman tree. At one point I do this ("nodeList" is List(Node)):
Node node = new Node(nodeList[0], nodeList[1]);
nodeList.Add(node); // Adds a new node which includes two subnodes.
// Remove nodes from list (as they are now included in another node)
nodeList.RemoveAt(0);
nodeList.RemoveAt(1);
And the constructors in use here is:
// Constructor that takes nodes
public Node(Node left, Node right)
{
leftNode = new Node(left);
rightNode = new Node(right);
}
// Constructor that only takes 1 single node
public Node(Node copy)
{
rightNode = copy.rightNode;
leftNode = copy.leftNode;
unencodedBits = copy.unencodedBits;
encodingValue = copy.encodingValue;
positions = copy.positions;
}
I did the second constructor as a hope that it would fix my problem (thinking that removing the node from the list maybe nulled it out.) (all of the values in my Node-class is on the right side of the second constructor.)
The problem: After doing the second "RemoveAt" the Node will no longer contain the two nodes. And I can not understand why. What do I have to do to prevent this from happening and why does it happen (so I can understand similar cases in the future)?
I probably forgot to include some vital information; If I did, please tell me. And thanks for any assistance.
Is your nodeList object in array or a List? If it is a list, then nodeList.RemoveAt(0) causes the node currently located and index 1 to now be located at index 0. so you would need to call
nodeList.RemoveAt(0);
nodeList.RemoveAt(0);
instead of
nodeList.RemoveAt(0);
nodeList.RemoveAt(1);
see here: http://msdn.microsoft.com/en-us/library/5cw9x18z(v=vs.110).aspx
I've been working a lot with tree implementations lately and how we represent and understand trees. My focus has been on turning mathematical expressions into binary trees, I set the problem of representing a tree in a linear form say a string or an array, while still retaining important information about the tree and its sub trees.
As such I have developed a really simple encoding for binary expression trees does just this. However I am having some issues with implementing it effectively in a recursive manor, it seems to be the one failing aspect behind the concept.
The encoding is simple if the node resides as a left child it is given a map of 1 if it resides as a right child it is given a 0. This simple encoding allows me to encode entire balanced and unbalanced trees like this:
## ##
/ \ / \
1 0 OR 1 0
/ \ / \ / \
11 10 01 00 01 00
Etc to trees of depth N
Does anyone have any suggestions as to how to create a recursive function that would create the prefix string representing a mapping of this sort (for example ## 1 11 10 0 01 00).
I was told this would be difficult/impossible due to having to keep track of alternating between 1 and 0 while retaining and concatenating to the value of the parent.
I wondered if anyone had any insight or ideas into how to do this with C# ??
I'm not sure I understand you problem but here is something that might help. One solution might be implementing graph traversal routine on a Graph (remember a Tree is a specialized Graph), where the visit occurs the first time you encounter a node/vertex. I apologize for posting Java code when you asked for C# but I happen know Java...
public void depthFirstSearch(Graph graph, Vertex start){
Set<Vertex> visited = new HashSet<Vertex>(); // could use vertex.isVisited()...
Deque<Vertex> stack = new ArrayDeque<Vertex>(); // stack implies depth first
// first visit the root element, then add it to the stack so
// we will visit it's children in a depth first order
visit(start);
visited.add(start);
stack.push(start);
while(stack.isEmpty() == false){
List<Edge> edges = graph.getEdges(stack.peekFirst());
Vertex nextUnvisited = null;
for(Edge edge : edges){
if(visited.contains(edge.getEndVertex)) == false){
nextUnvisited = edge.getEndVertex();
break; // break for loop
}
}
if(nextUnvisited == null){
// check the next item in the stack
Vertex popped = stack.pop();
} else {
// visit adjacent unvisited vertex
visit(nextUnvisited);
visited.add(nextUnvisited);
stack.push(nextUnvisited); // visit it's "children"
}
}
}
public void visit(Vertex vertex){
// your own visit logic (string append, etc)
}
You can easily modify this to be a breadth first search by using the Deque as a queue instead of stack as follows:
stack.pop() >>>> queue.removeFirst()
stack.push() >>>> queue.addLast()
Note that for this purpose the Graph and Edge classes support the following operations :
public interface Graph {
...
// get edges originating from Vertex v
public List<Edge> getEdges(Vertex v);
...
}
public interface Edge {
...
// get the vertex at the start of the edge
// not used here but kind of implied by the getEndVertex()...
public Vertex getStartVertex();
// get the vertex at the end of the edge
public Vertex getEndVertex();
...
}
Hopefully that gives you some ideas.
Well i don't know if i completely get your question but it seems you want a preorder traversal of the tree. I don't know c#'s syntax but the pseudocode i think will be as follows:
preorder_traversal(node)
if(node != NULL)
print(node)
preorder_traversal(left_sub_child)
preorder_traversal(right_sub_child)
else
return
Building a tree recursively is a difficult challenge even for a seasoned programmer. I realize I'm a bit late to the party on this question considering it was originally posted in March of 2011. Better late than never?
One important factor in creating a tree is just making sure your dataset is formatted correctly. You simply need a way to associate a parent to a child. Once the association is clearly defined, then you can begin to code the solution. I chose to use a simple format like this:
ParentId ChildId
1 2
1 3
2 4
3 5
Etc.
Once that relationship is established, I developed a recursive method to iterate through the dataset to build the tree.
First I identify all the parent nodes and store them in a collection giving them each a unique identifier using a combination of the parent ID and child ID:
private void IdentifyParentNodes()
{
SortedList<string, MyTreeNode> newParentNodes = new SortedList<string,MyTreeNode>();
Dictionary<string, string> parents = new Dictionary<string, string>();
foreach (MyTreeNode oParent in MyTreeDataSource.Values)
{
if (!parents.ContainsValue(oParent.ParentId))
{
parents.Add(oParent.ParentId + "." + oParent.ChildId, oParent.ParentId);
newParentNodes.Add(oParent.ParentId + "." + oParent.ChildId, oParent);
}
}
this._parentNodes = newParentNodes;
}
Then the root calling method would loop through the parents and call the recursive method to build the tree:
// Build the rest of the tree
foreach (MyTreeNode node in ParentNodes.Values)
{
RecursivelyBuildTree(node);
}
Recursive method:
private void RecursivelyBuildTree(MyTreeNode node)
{
int nodePosition = 0;
_renderedTree.Append(FormatNode(MyTreeNodeType.Parent, node, 0));
_renderedTree.Append(NodeContainer("open", node.ParentId));
foreach (MyTreeNode child in GetChildren(node.ParentId).Values)
{
nodePosition++;
if (IsParent(child.ChildId))
{
RecursivelyBuildTree(child);
}
else
{
_renderedTree.Append(FormatNode(MyTreeNodeType.Leaf, child, nodePosition));
}
}
_renderedTree.Append(NodeContainer("close", node.ParentId));
}
Method used to get children of a parent:
private SortedList<string, MyTreeNode> GetChildren(string parentId)
{
SortedList<string, MyTreeNode> childNodes = new SortedList<string, MyTreeNode>();
foreach (MyTreeNode node in this.MyTreeDataSource.Values)
{
if (node.ParentId == parentId)
{
childNodes.Add(node.ParentId + node.ChildId, node);
}
}
return childNodes;
}
Not that complex or elegant, but it got the job done. This was written in 2007 time frame, so it's old code, but it still works. :-) Hope this helps.
I am having trouble implementing a sort algo (merge) for singly list as defined below
My mergesort method always gives me null..I am not able to figure out what is wrong
Can you guys help me out?
Node class
public class Node
{
private int data;
private Node next;
}
Linked List class
public class SSL
{
private Node head;
}
My merge sort code
public static void MergeSort(SSL a)
{
SSL x = new SSL();
SSL y = new SSL();
if (a.Head == null || a.Head.Next == null) // base case if list has 0 or 1 element
return;
AlternateSplitting(a, x, y);
MergeSort(x);
MergeSort(y);
a = SortedMerge(x, y);
}
I implemented following helper methods to implement merge sort
AlternateSplitting: This method will split the list into 2 lists
public static void AlternateSplitting(SSL src, SSL odd, SSL even)
{
while (src.Head != null)
{
MoveNode(odd, src);
if (src.Head != null)
MoveNode(even, src);
}
} // end of AlternateSplitting
This method will merge the 2 list and return a new list
public static SSL SortedMerge(SSL a, SSL b)
{
SSL c = new SSL();
if (a.Head == null)
return b;
else
if (b.Head == null)
return a;
else
{
bool flagA = false;
bool flagB = false;
Node currentA = new Node();
Node currentB = new Node();
while (!flagA && !flagB)
{
currentA = a.Head;
currentB = b.Head;
if (currentA.Data < currentB.Data)
{
MoveNodeToEnd(a, c);
currentA = a.Head;
if (currentA== null)
flagA = true;
}
else
if (currentA.Data > currentB.Data)
{
MoveNodeToEnd(b, c);
currentB = b.Head;
if (currentB== null)
flagB = true;
}
} // end of while
if (flagA)
{
while (currentB != null)
{
MoveNodeToEnd(b, c);
currentB = b.Head;
}
}
else
if(flagB)
{
while (currentA != null)
{
MoveNodeToEnd(a, c);
currentA = a.Head;
}
}
return c;
} // end of outer else
} // end of function sorted merge
I am not able to figure out what is
wrong Can you guys help me out?
Find a bug and you fix it for a day. Teach how to find bugs and believe me, it takes a lifetime to fix the bugs. :-)
Your fundamental problem is not that the algorithm is wrong -- though, since it gives incorect results, it certainly is wrong. But that's not the fundamental problem. The fundamental problem is that you don't know how to figure out where a program goes wrong. Fix that problem first! Learn how to debug programs.
Being able to spot the defect in a program is an acquired skill like any other -- you've got to learn the basics and then practice for hundreds of hours. So learn the basics.
Start by becoming familiar with the basic functions of your debugger. Make sure that you can step through programs, set breakpoints, examine local variables, and so on.
Then write yourself some debugging tools. They can be slow -- you're only going to use them when debugging. You don't want your debugging tools in the production version of your code.
The first debugging tool I would write is a method that takes a particular Node and produces a comma-separated list of the integers that are in the list starting from that node. So you'd say DumpNode(currentB) and what would come back is, say "{10,20,50,30}". Obviously doing the same for SSL is trivial if you can do it for nodes.
I would also write tools that do things like count nodes in a list, tell you whether a given list is already sorted, and so on.
Now you have something you can type into the watch window to more easily observe the changes to your data structures as they flow by. (There are ways to make the debugger do this rendering automatically, but we're discussing the basics here, so let's keep it simple.)
That will help you understand the flow of data through the program more easily. And that might be enough to find the problem. But maybe not. The best bugs are the ones that identify themselves to you, by waving a big red flag that says "there's a bug over here". The tool that turns hard-to-find bugs into self-identifying bugs is the debug assertion.
When you're writing your algorithm, think "what must be true?" at various points. For example, before AlternateSplitting runs, suppose the list has 10 items. When it is done running, the two resulting lists had better have 5 items each. If they don't, if they have 10 items each or 0 items each or one has 3 and the other has 7, clearly you have a bug somewhere in there. So start writing debug-only code:
public static void AlternateSplitting(SSL src, SSL odd, SSL even)
{
#if DEBUG
int srcCount = CountList(src);
#endif
while (src.Head != null) { blah blah blah }
#if DEBUG
int oddCount = CountList(odd);
int evenCount = CountList(even);
Debug.Assert(CountList(src) == 0);
Debug.Assert(oddCount + evenCount == srcCount);
Debug.Assert(oddCount == evenCount || oddCount == evenCount + 1);
#endif
}
Now AlternateSplitting will do work for you in the debug build to detect bugs in itself. If your bug is because the split is not working out correctly, you'll know immediately when you run it.
Do the same thing to the list merging algorithm -- figure out every point where "I know that X must be true at this point", and then write a Debug.Assert(X) at that point. Then run your test cases. If you have a bug, then the program will tell you and the debugger will take you right to it.
Good luck!