I'm really struggling to get this method to work, I was wondering if you could help me out. I've been using the ref keyword, so I'll keep using it. I've been searching the web and it's been some help, but I've tried everything I can possibly think of. Both my count and height methods work, however, I'm just really struggling to get this Contain method to work. Many examples on the web have showed both a public and private method of contains (I understand as to why) but I'm sure it could be done within one method? Surely, right? Also, please ignore the RemoveItem method, unless you wish to give me a head-start, that's at your discretion. I know it's tricky as I've looked up on it earlier during the week.
Node class-
class Node<T> where T : IComparable
{
private T data;
public Node<T> Left, Right;
public Node(T item)
{
data = item;
Left = null;
Right = null;
}
public T Data
{
set { data = value; }
get { return data; }
}
}
BinTree Class-
class BinTree<T> where T : IComparable
{
protected Node<T> root;
public BinTree() //creates an empty tree
{
root = null;
}
public BinTree(Node<T> node) //creates a tree with node as the root
{
root = node;
}
//I've deleted my preOrder, inOrder and postOrder methods just to save you some time
}
BSTree Class-
class BSTree<T> : BinTree<T> where T : IComparable
{
public BSTree()
{
root = null;
}
private void insertItem(T item, ref Node<T> tree)
{
if (tree == null)
{
tree = new Node<T>(item);
}
else if (item.CompareTo(tree.Data) < 0)
{
insertItem(item, ref tree.Left);
}
else if (item.CompareTo(tree.Data) > 0)
insertItem(item, ref tree.Right);
}
public void InsertItem(T item)
{
insertItem(item, ref root);
}
public int Height(ref Node<T> tree)
//Return the max level of the tree
{
if (tree == null)
return 0;
return (1 + Math.Max(Height(ref tree.Left), Height(ref tree.Right)));
}
public int Count(ref Node<T> tree)
//Return the number of nodes in the tree
{
int counter = 0;
if (tree == null)
{
return 0;
}
else if (tree.Left != null)
{
counter += Count(ref tree.Left);
counter++;
}
if (tree.Right != null)
{
counter += Count(ref tree.Right);
counter++;
}
return counter;
}
public Boolean Contains(T item, ref Node<T> tree)
//Return true if the item is contained in the BSTree, false //otherwise.
{
if (tree == null)
{
return false;
}
if (item.CompareTo(tree.Data) < 0)
{
return Contains(ref tree.Left);
if (item.CompareTo(tree.Data) > 0)
{
return Contains(ref tree.Right);
return true;
}
}
}
public void RemoveItem(T item)
{
}
}
Thank you in advance.
To check if a node is in the tree, you have a few options:
The node you want is in the left sub-tree
The node you want is in the right sub-tree
The node you want is where you are right now
So your Contains method should look more like this:
public Boolean Contains(T item, ref Node<T> tree)
{
if (tree == null)
{
return false;
}
if (tree.data == item)
{
return true;
}
if (item.CompareTo(tree.Data) < 0)
{
return Contains(item, ref tree.Left);
}
if (item.CompareTo(tree.Data) > 0)
{
return Contains(item, ref tree.Right);
}
}
public static bool Contains(Node root, int value)
{
if(root == null)
return false;
if(root.Value == value)
return true;
if(value < root.Value)
return Contains( root.Left,value);
else
return Contains( root.Right,value);
}
Related
here i have the following code and input that prints a tree structure. My question is how can i make it so that the nodes and leafs that have the value "Unavailable" are skipped from being printed.
namespace Tree{public class TreeNode<T>
{
private T value;
private bool hasParent;
private List<TreeNode<T>> children;
public TreeNode(T value)
{
if (value == null)
{
throw new ArgumentNullException("Cannot insert null value");
}
this.value = value;
this.children = new List<TreeNode<T>>();
}
public T Value
{
get
{
return this.value;
}
set
{
this.value = value;
}
}
public int ChildrenCount
{
get
{
return this.children.Count;
}
}
public void AddChild(TreeNode<T> child)
{
if (child == null)
{
throw new ArgumentNullException("Cannot insert null value");
}
if (child.hasParent)
{
throw new ArgumentException("The node already has a parent");
}
child.hasParent = true;
this.children.Add(child);
}
public TreeNode<T> GetChild(int index)
{
return this.children[index];
}
}
public class Tree<T>
{
private TreeNode<T> root;
public Tree(T value)
{
if (value == null)
{
throw new ArgumentNullException("Cannot insert null value");
}
this.root = new TreeNode<T>(value);
}
public Tree(T value, params Tree<T>[] children) : this(value)
{
foreach (Tree<T> child in children)
{
this.root.AddChild(child.root);
}
}
public TreeNode<T> Root
{
get
{
return this.root;
}
}
private void PrintDFS(TreeNode<T> root, string spaces)
{
if (this.root == null)
{
return;
}
Console.WriteLine(spaces + root.Value);
TreeNode<T> child = null;
for (int i = 0; i < root.ChildrenCount; i++)
{
child = root.GetChild(i);
PrintDFS(child, spaces + " ");
}
}
public void TraverseDFS()
{
this.PrintDFS(this.root, string.Empty);
}
}
public static class TreeExample
{
static void Main()
{
Tree<string> tree =
new Tree<string>("John",
new Tree<string>("Jasmine",
new Tree<string>("Jay"),
new Tree<string>("Unavailable")),
new Tree<string>("Unavailable",
new Tree<string>("Jack"),
new Tree<string>("Jeremy")),
new Tree<string>("Johanna")
);
tree.TraverseDFS();
}
}}
right now it prints :(John, (Jasmine, (Jay), (Unavailable)), (Unavailable, (Jack, (Jeremy))), (Johanna))
I need it to print :(John, (Jasmine, (Jay)), (Johanna))
So basically skip every leaf with the value "Unavailable" and every node with the value "Unavailable" and all children from that node
Thanks !
This should work:
private void PrintDFS(TreeNode<T> root, string spaces)
{
if (this.root == null
|| "Unavailable" == root.Value.ToString())
{
return;
}
...
The accepted answer is a literally correct answer to the question, but it bakes in logic about what to do with the tree into the tree itself. A tree is a kind of collection or data structure, and you don't often see a List or Dictionary that is able to print itself. Instead the collection provides the right methods to get or change its contents so that you can do what you want.
In your case, you could do something like the following:
public enum TreeVisitorResult {
SkipNode,
Continue
}
// the following two methods inside Tree<T>:
public void VisitNodes(Func<TreeNode<T>, int, TreeVisitorResult> visitor) {
VisitNodes(0, this.root, visitor);
}
private void VisitNodes(int depth, TreeNode<T> node,
Func<TreeNode<T>, int, TreeVisitorResult> visitor) {
if (node == null) {
return;
}
var shouldSkip = visitor(node, depth);
if (shouldSkip == TreeVisitorResult.SkipNode) {
return;
}
TreeNode<T> child = null;
for (int i = 0; i < node.ChildrenCount; i++) {
child = node.GetChild(i);
VisitNodes(depth + 1, child, visitor);
}
}
If you had this method, you could write the Print method outside of the Tree classes, as:
tree.VisitNodes((treeNode, depth) => { // <- this lambda will be called for every node
if (treeNode.Value == "Unavailable") { // <- no need to ToString or cast here, since
// we know that T is string here
return TreeVisitorResult.SkipNode;
} else {
var spaces = new string(' ', depth * 3);
Console.WriteLine(spaces + treeNode.Value);
}
});
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 4 years ago.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Improve this question
When I run my program my 'if' statement is compiled as unreachable code which in turn, causes my contains method to continuously print false even though the number exists within the tree. I can't figure out why could any one help me please? I'm fairly new to programming.
Here is my node class.
class Node<T> where T : IComparable
{
private T data;
private int balanceFactor = 0; //added for AVLTree
public Node<T> Left, Right;
public Node(T item)
{
data = item;
Left = null;
Right = null;
}
public T Data
{
set { data = value; }
get { return data; }
}
}
Here is my binary search tree class.
class BSTree<T> : BinTree<T> where T : IComparable
{ //root declared as protected in Parent Class – Binary Tree
public BSTree()
{
root = null;
}
public void InsertItem(T item)
{
insertItem(item, ref root);
}
private void insertItem(T item, ref Node<T> tree)
{
if (tree == null)
tree = new Node<T>(item);
else if (item.CompareTo(tree.Data) < 0)
insertItem(item, ref tree.Left);
else if (item.CompareTo(tree.Data) > 0)
insertItem(item, ref tree.Right);
}
public int Height()
//Return the max level of the tree
{
return Height(root);
}
protected int Height(Node<T> current)
{
if (current == null) return 0;
return 1 + Math.Max(Height(current.Left), Height(current.Right));
}
public int Count()
//Return the number of nodes in the tree
{
return Height(root);
}
public int Count(ref Node<T> current)
//Return the number of nodes in the tree
{
int counter = 0;
if (current == null)
{
return 0;
}
else if (current.Left != null)
{
counter += Count(ref current.Left);
counter++;
}
if (current.Right != null)
{
counter += Count(ref current.Right);
counter++;
}
return counter;
}
public Boolean Contains(T item)
//Return true if the item is contained in the BSTree, false //otherwise.
{
Node<T> current = root;
if (current.Data.CompareTo(item) == 0)
{
{
return true;
}
if (current.Data.CompareTo(item) > 0)
{
current = current.Left;
}
if (current.Data.CompareTo(item) < 0)
{
current = current.Right;
}
}
return false;
}
private T leastItem(Node<T> tree)
{
if (tree.Left == null)
return tree.Data;
else
return leastItem(tree.Left);
}
}
Lastly my main class.
class Program
{
static void Main(string[] args)
{
BSTree<int> treeBranch = new BSTree<int>();
treeBranch.InsertItem(77);
treeBranch.InsertItem(20);
treeBranch.InsertItem(37);
treeBranch.InsertItem(15);
treeBranch.InsertItem(22);
treeBranch.InsertItem(30);
Console.WriteLine(treeBranch.Count());
Console.WriteLine(treeBranch.Height());
Console.WriteLine(treeBranch.Contains(15));
string InOrder = "in order :";
treeBranch.InOrder(ref InOrder);
Console.WriteLine(InOrder);
Console.WriteLine("\n");
Console.ReadKey();
}
}
if (current.Data.CompareTo(item) == 0)
{
{ <==== here
return true;
}
if (current.Data.CompareTo(item) > 0)
{
current = current.Left;
}
if (current.Data.CompareTo(item) < 0)
{
current = current.Right;
}
}
There's no condition to return true;. Change your code to this:
if (current.Data.CompareTo(item) == 0)
{
return true;
}
else if (current.Data.CompareTo(item) > 0)
{
current = current.Left;
}
else if (current.Data.CompareTo(item) < 0)
{
current = current.Right;
}
To many { and } in this code
if (current.Data.CompareTo(item) == 0)
{
{
return true;
}
I am using ref so that it changes the root of the Binary Search Tree I am trying to create, however, it's not working the way I intend for it to.
public BinaryNode<T> Root { get; set; }
public BinaryTree() : base()
{
Root = null;
public T Insert(ref BinaryNode<T> root, T val)
{
// Insert here
if (root == null)
{
BinaryNode<T> newNode = new BinaryNode<T>(val);
root = newNode;
Size++;
return val;
}
if (val.CompareTo(root.Data) < 0)
{
BinaryNode<T> left = root.LeftChild;
return Insert(ref left, val);
}
else if (val.CompareTo(root.Data) > 0)
{
BinaryNode<T> right = root.RightChild;
return Insert(ref right, val);
}
return val;
}
public override T Insert(T val)
{
BinaryNode<T> root = Root;
return Insert(ref root, val);
}
I was expecting that when I do root = newNode that for example Root would change during the first insert. However, this is not the case. Root stays null even after. I am suspecting that this is something more related to properties and how it interacts with ref instead of ref itself?
You are modifying the local root variable since that's the reference you are passing in. If you want this to work you need to then assign it back to the Root property like so:
public T Insert(T val)
{
BinaryNode<T> root = Root;
var result = Insert(ref root, val);
Root = root;
return result;
}
Perhaps a cleaner option would be to directly use a backing field for the property like so:
BinaryNode<T> _root;
public BinaryNode<T> Root
{
get { return _root; }
set { _root = value; }
}
public T Insert(T val)
{
return Insert(ref _root, val);
}
I made a Tree Data Structure and I want the Elements to sort like this:
10
/ \
5 12
/ \ / \
3 7 11 18
If the value of the added element is smaller than the value of the other element, it should be linked left, and if bigger, right. My problem is, that I just can't get the sorting method right.
class Tree
{
private class TElement
{
public int _value;
public TElement _left;
public TElement _right;
public TElement(int value)
{
_value = value;
}
}
private TElement RootElement;
public void Add(int value)
{
TElement newElement = new TElement(value);
TElement current = new TElement(value);
current = RootElement;
if (RootElement == null)
{
RootElement = newElement;
return;
}
SortNewElement(RootElement, RootElement, newElement, RootElement);
}
private void SortNewElement(TElement left, TElement right, TElement newElement, TElement RootElement)
{
if (newElement._value < RootElement._value && RootElement._left == null)
{
left._left = newElement;
return;
}
if (newElement._value > RootElement._value && RootElement._right == null)
{
right._right = newElement;
return;
}
if (newElement._value < left._value && left._left == null)
{
left._left = newElement;
return;
}
if (newElement._value > right._value && right._right == null)
{
right._right = newElement;
return;
}
SortNewElement(left._left, right._right, newElement, RootElement);
}
}
I know it doesn't work because it's trying to get the linked nodes of a null element.
From what i can understand from your question you are just trying to insert a new node in a binary search tree. Its inorder traversal will be a sorted array.
You can do so by the following simple pseudo code
insert_new( Node* node, value)
{
if(value > node->value)
{
if(node->right != null)
{
insert_new(node->right,value);
}
else
{
node->right = new Node(value);
return;
}
}
else
{
if(node->left != null)
{
insert_new(node->left,value)
}
else
{
node->left = new Node(value);
return;
}
}
}
class element{
public:
int value;
*element left;
*element right;
element(int value)
value = value;
public add(&element a)
if (a != null)
{
if (left!=null){
left = a;
}
else{
if (left.value > a.value){
right = left;
left= a;
}
else{
right=a;
}
}
I was just doing some research on RedBlack Tree. I knew that SortedSet class in .Net 4.0 uses RedBlack tree. So I took that part out as is using Reflector and created a RedBlackTree class. Now I am running some perf test on this RedBlackTree and SortedSet inserting 40000 sequential integral values (starting from 0 to 39999), I am astonished to see that there is huge perf difference as follows:
RBTree took 9.27208 sec to insert 40000 values
SortedSet took 0.0253097 sec to insert 40000 values
What is the reason behind it? BTW I ran the test in Release configuration only and here is the small test code
var stopWatch = new Stopwatch();
var rbT = new RedBlackTree<int>();
stopWatch = new Stopwatch();
stopWatch.Start();
for (int i = 0; i < 40000; i++) {
rbT.Add(i);
}
stopWatch.Stop();
Console.WriteLine(stopWatch.Elapsed);
var ss = new SortedSet<int>();
stopWatch = new Stopwatch();
stopWatch.Start();
for (int i = 0; i < 40000; i++) {
ss.Add(i);
}
stopWatch.Stop();
Console.WriteLine(stopWatch.Elapsed);
Edit
I would like to share the code also for RBTree what I've extracted so that you also can run the diagnostics
public class Node<T>
{
public Node(){}
public Node(T value)
{
Item = value;
}
public Node(T value, bool isRed)
{
Item = value;
IsRed = isRed;
}
public T Item;
public Node<T> Left;
public Node<T> Right;
public Node<T> Parent;
public bool IsRed;
}
public class RedBlackTree<T>
{
public RedBlackTree(){}
public Node<T> root;
int count, version;
Comparer<T> comparer = Comparer<T>.Default;
public void Add(T item)
{
if (this.root == null)
{
this.root = new Node<T>(item, false);
this.count = 1;
this.version++;
return;
}
Node<T> root = this.root;
Node<T> node = null;
Node<T> grandParent = null;
Node<T> greatGrandParent = null;
this.version++;
int num = 0;
while (root != null)
{
num = this.comparer.Compare(item, root.Item);
if (num == 0)
{
this.root.IsRed = false;
return;
}
if (Is4Node(root))
{
Split4Node(root);
if (IsRed(node))
{
this.InsertionBalance(root, ref node, grandParent, greatGrandParent);
}
}
greatGrandParent = grandParent;
grandParent = node;
node = root;
root = (num < 0) ? root.Left : root.Right;
}
Node<T> current = new Node<T>(item);
if (num > 0)
{
node.Right = current;
}
else
{
node.Left = current;
}
if (node.IsRed)
{
this.InsertionBalance(current, ref node, grandParent, greatGrandParent);
}
this.root.IsRed = false;
this.count++;
}
private static bool IsRed(Node<T> node)
{
return ((node != null) && node.IsRed);
}
private static bool Is4Node(Node<T> node)
{
return (IsRed(node.Left) && IsRed(node.Right));
}
private static void Split4Node(Node<T> node)
{
node.IsRed = true;
node.Left.IsRed = false;
node.Right.IsRed = false;
}
private void InsertionBalance(Node<T> current, ref Node<T> parent, Node<T> grandParent, Node<T> greatGrandParent)
{
Node<T> node;
bool flag = grandParent.Right == parent;
bool flag2 = parent.Right == current;
if (flag == flag2)
{
node = flag2 ? RotateLeft(grandParent) : RotateRight(grandParent);
}
else
{
node = flag2 ? RotateLeftRight(grandParent) : RotateRightLeft(grandParent);
parent = greatGrandParent;
}
grandParent.IsRed = true;
node.IsRed = false;
ReplaceChildOfNodeOrRoot(greatGrandParent, grandParent, node);
}
private static Node<T> RotateLeft(Node<T> node)
{
Node<T> right = node.Right;
node.Right = right.Left;
right.Left = node;
return right;
}
private static Node<T> RotateRight(Node<T> node)
{
Node<T> left = node.Left;
node.Left = left.Right;
left.Right = node;
return left;
}
private static Node<T> RotateLeftRight(Node<T> node)
{
Node<T> left = node.Left;
Node<T> right = left.Right;
node.Left = right.Right;
right.Right = node;
left.Right = right.Left;
right.Left = left;
return right;
}
private static Node<T> RotateRightLeft(Node<T> node)
{
Node<T> right = node.Right;
Node<T> left = right.Left;
node.Right = left.Left;
left.Left = node;
right.Left = left.Right;
left.Right = right;
return left;
}
private void ReplaceChildOfNodeOrRoot(Node<T> parent, Node<T> child, Node<T> newChild)
{
if (parent != null)
{
if (parent.Left == child)
{
parent.Left = newChild;
}
else
{
parent.Right = newChild;
}
}
else
{
this.root = newChild;
}
}
}
Edit
I ran the same diagnostic on some other data structure (some created by me*, some from .net framework**) and here is the interesting results
*AATree 00:00:00.0309294
*AVLTree 00:00:00.0129743
**SortedDictionary 00:00:00.0313571
*RBTree 00:00:09.2414156
**SortedSet 00:00:00.0241973
RBTree is the same as above (stripped out from SortedSet class). I tried with 400000 values also, but RBTree seems taking FOREVER, I really don't know why.
You have a bug in your Node<T> class. When you call the constructor that only takes a single value argument you should be setting IsRed to true.
I suppose that the fixed Node<T> class should look something like this:
public sealed class Node<T>
{
public T Item { get; private set; }
public bool IsRed { get; set; }
public Node<T> Left { get; set; }
public Node<T> Right { get; set; }
public Node(T value)
{
Item = value;
IsRed = true;
}
public Node(T value, bool isRed)
{
Item = value;
IsRed = isRed;
}
}
Another option -- my preference -- would be to omit that constructor altogether and always require IsRed to be set explicitly when you instantiate a new node:
public sealed class Node<T>
{
public T Item { get; private set; }
public bool IsRed { get; set; }
public Node<T> Left { get; set; }
public Node<T> Right { get; set; }
public Node(T value, bool isRed)
{
Item = value;
IsRed = isRed;
}
}
And then replace this line in your Add method...
Node<T> current = new Node<T>(item);
...with this...
Node<T> current = new Node<T>(item, true);
reverse the order of the tests and repeat the measurement.
randomize your data. Sorted sets behave strangely when you insert pre-sorted data.
SortedSet includes a TargetedPatchingOptOut attribute, did your copied version include that?
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public bool Add(T item)
{
return this.AddIfNotPresent(item);
}
If the difference wasn't that big I would suggest that the cause is that the .NET assemblies are NGen-ed and so they are already translated to native code. In the case of your class the time to compile the IL code into native code is amortized over the time of your test. How does increasing the number of loop iterations affect the times?