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);
}
});
Related
I have only started learning Data Structures so please bear my stupidity, I am trying to develop my own version of BST, I can't get why there is a need of a parent Node? Shouldn't this work just fine.
class BST
{
private Node root;
public BST()
{
root = null;
}
public void insert(int value)
{
Node temp = new Node();
temp.value = value;
if (root == null)
{
root = temp;
return;
}
Node current = root;
while (current != null)
{
if (value <= current.value)
{
current = current.lc;
}
else
{
current = current.rc;
}
}
current = temp;
}
}
class Node
{
public Node lc;
public int value;
public Node rc;
}
There is definitely something that I am missing and I can't grasp or get what it is, when current is null, we are already onto where we need to insert the node, why then do we need a parent node.
This may work
class BST
{
private Node root = null;
public void insert(int value)
{
Node temp = new Node { value = value };
if (root == null)
{
root = temp;
return;
}
var current = root;
while (current != null)
{
if (value <= current.value)
{
if (current.lc == null)
{
current.lc = temp;
break;
}
current = current.lc;
}
else
{
if (current.rc == null)
{
current.rc = temp;
break;
}
current = current.rc;
}
}
}
}
class Node
{
public Node lc;
public int value;
public Node rc;
}
You are mixing variables with references to fields/variables. The current variable holds the value of the lc or rc field (the copy of the field). Setting the variable does not set the corresponding field, just assigns another value to the variable.
Hence the line
current = temp;
does not insert the node in the BST.
What you are trying to do is possible with C#7.0 introduced ref locals and returns and C#7.3 introduced improvements which allow to reassign ref local variables.
The ref local variables are exactly what is your intention - they contain the location (reference, address) of some other field / variable. So the following works (requires C#7.3!):
public void insert(int value)
{
ref Node nodeRef = ref root;
while (nodeRef != null)
{
if (value <= nodeRef.value)
nodeRef = ref nodeRef.lc;
else
nodeRef = ref nodeRef.rc;
}
nodeRef = new Node { value = value };
}
Note the usage of ref keyword. You use nodeRef = ref … to assign a reference (address) of a variable (in this case either root or some node lc or rc field), and nodeRef = … to assign a value to the variable pointed by the nodeRef.
You are setting "null" to some instance.
In your while loop current eventually becomes null, and you are missing the connection between nodes.
To fix this issue you should keep the last node of your tree.
You can try the below :
class BST
{
private Node root;
public BST()
{
root = null;
}
public void insert(int value)
{
root = insert(root, value);
}
private Node insert(Node node, int value) {
// if the given node is null it should be new node
if (node == null) {
node = new Node();
node.value = value;
return node;
}
if (value < node.value)
// if our value lower then current value then we will insert left node recursively
node.lc = insert(node.lc, value);
else if (value > node.value)
// if our value higher then current value then we will insert right node recursively
node.rc = insert(node.rc, value);
return node;
}
public void print() {
print(root);
}
private void print(Node node) {
if (node != null) {
print(node.lc);
Console.WriteLine(node.value);
print(node.rc);
}
return;
}
}
public static void main(String[] args) {
BST bst = new BST();
bst.insert(5);
bst.insert(25);
bst.insert(15);
bst.insert(4);
bst.print();
}
The output is :
4
5
15
25
I want to implement simple Linked list and adding items and its seems that my Add function get into endless loop and i don't know why
public class IntNode
{
private int _value;
private IntNode _next;
public IntNode(int val, IntNode n)
{
_value = val;
_next = n;
}
public int getValue()
{
return _value;
}
public IntNode getNext()
{
return _next;
}
public void setValue(int v)
{
_value = v;
}
public void setNext(IntNode next)
{
_next = next;
}
public string ToString()
{
return _value.ToString();
}
}
public class IntList
{
private IntNode _head;
public static int count;
public IntList()
{
_head = null;
count = 0;
}
public IntList(IntNode node)
{
_head = node;
}
public void Add(IntNode node)
{
if (_head == null)
_head = node;
else
{
for (IntNode p = _head; p.getNext() != null; p.getNext()) { }
_head.setNext(node);
count++;
}
}
public void ToString()
{
IntNode cur = _head;
while (cur.getNext() != null)
{
Console.WriteLine(cur.ToString());
cur = cur.getNext();
}
}
}
main
static void Main(string[] args)
{
IntList list = new IntList();
list.Add(new IntNode(5, null));
list.Add(new IntNode(2, null));
list.Add(new IntNode(8, null));
list.Add(new IntNode(1, null));
list.ToString();
}
The problem is the increment step in the for loop. It needs to be p = p.getNext() not simply p.getNext(). The latter just calls the getNext function and does nothing with the return which means p is never modified and hence the loop doesn't make any progress
for (IntNode p = _head; p.getNext() != null; p = p.getNext()) { }
The next problem is you are not actually moving _head or using the p value. Hence you haven't actually found the place to insert. What you need is something like the following
IntNode p = _head;
while (p.getNext() != null) {
p = p.getNext();
}
p.setNext(node);
for (IntNode p = _head; p.getNext() != null; p.getNext()) { }
You're not using p anywhere, and not doing anything in the loop body. Can you spot your problem?
First, you don't assign the result of getNext() anywhere:
for (IntNode p = _head; p.getNext() != null; p.getNext()) { }
Second, you even don't use the last node anywhere. In fact, you even couldn't, because p doesn't exist outside of the for loop…
Advice: Keep a reference to the last node as well and make your life simpler.
Your loop never ends because p is not incremented.
It should be easier for you if you keep a reference to the last inserted item. For example :
private IntNode _lastNode;
public void Add(IntNode node)
{
if (_head == null)
_head = node;
else
{
if (_lastNode == null)
_lastNode = _head;
_lastNode.setNext(node)
_lastNode = node;
}
count++;
}
You won't have to loop through nodes each time you try to add a node.
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;
}
}
class Node
{
public int data;
public Node left, right;
public Node(int data)
{
this.data = data;
left = null;
right = null;
}
}
class BinaryTreeImp
{
Node root;
static int count = 0;
public BinaryTreeImp()
{
root = null;
}
public Node addNode(int data)
{
Node newNode = new Node(data);
if (root == null)
{
root = newNode;
}
count++;
return newNode;
}
public void insertNode(Node root,Node newNode )
{
Node temp;
temp = root;
if (newNode.data < temp.data)
{
if (temp.left == null)
{
temp.left = newNode;
}
else
{
temp = temp.left;
insertNode(temp,newNode);
}
}
else if (newNode.data > temp.data)
{
if (temp.right == null)
{
temp.right = newNode;
}
else
{
temp = temp.right;
insertNode(temp,newNode);
}
}
}
public void displayTree(Node root)
{
Node temp;
temp = root;
if (temp == null)
return;
displayTree(temp.left);
System.Console.Write(temp.data + " ");
displayTree(temp.right);
}
static void Main(string[] args)
{
BinaryTreeImp btObj = new BinaryTreeImp();
Node iniRoot= btObj.addNode(5);
btObj.insertNode(btObj.root,iniRoot);
btObj.insertNode(btObj.root,btObj.addNode(6));
btObj.insertNode(btObj.root,btObj.addNode(10));
btObj.insertNode(btObj.root,btObj.addNode(2));
btObj.insertNode(btObj.root,btObj.addNode(3));
btObj.displayTree(btObj.root);
System.Console.WriteLine("The sum of nodes are " + count);
Console.ReadLine();
}
}
This is the code for implementation.The code works fine but if in the displayTree function , i replace it with
public void displayTree(Node root)
{
Node temp;
temp = root;
while(temp!=null)
{
displayTree(temp.left);
System.Console.Write(temp.data + " ");
displayTree(temp.right);
}
}
an infinite loop is caused. I don't understand what is causing this.Also i would like to know if there is a better way of implementing a BST in C#.
I'm not sure why you need this loop, but answering your question:
while(temp!=null)
{
displayTree(temp.left);
System.Console.Write(temp.data + " ");
displayTree(temp.right);
}
this code checks if temp is not null, but it will never become null, cause inside the loop you act only on the leafs of the temp. That's why you have an infinit loop.
You don't need a while loop nor a temp variable, let recursion do the work for you:
public void displayTree(Node root)
{
if(root == null) return;
displayTree(root.left);
System.Console.Write(root.data + " ");
displayTree(root.right);
}
temp is set to root at the beginning, and after that its value never changes
what about rewriting your function as
public void displayTree(Node root)
{
if (root == null)
return;
displayTree(root.left);
Console.Write(...);
displayTree(root.right);
}
try this
public void displayTree(Node root)
{
Node temp;
temp = root;
if (temp != null)
{
displayTree(temp.left);
Console.WriteLine(temp.data + " ");
displayTree(temp.right);
}
}
I was just thinking that you as well also could use recursion for the add function. It could look something like this
private void Add(BinaryTree node, ref BinaryTree rootNode)
{
if (rootNode == null)
{
rootNode = node;
}
if (node.value > rootNode.value)
{
Add(node, ref rootNode.right);
}
if (node.value < rootNode.value)
{
Add(node, ref rootNode.left);
}
}
See https://msdn.microsoft.com/en-us/library/ms379572%28v=vs.80%29.aspx.
See the example code in the section "Traversing the Nodes of a BST"
Also... don't forget to check out SortedDictionary, etc. They may have the BST that you need all ready to go! https://msdn.microsoft.com/en-us/library/f7fta44c.aspx
Complete Binary Search Tree ... With Code to check whether Tree is balanced or not
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace BinarySearchTree
{
public class Node
{
public Node(int iData)
{
data = iData;
leftNode = null;
rightNode= null;
}
public int data{get; set;}
public Node leftNode{get; set;}
public Node rightNode{get; set;}
};
public class Program
{
public static Node root = null;
public static void Main(string[] args)
{
//Your code goes here
Console.WriteLine("Hello, world!");
root = new Node(20);
InsertNode(root, new Node(10));
InsertNode(root, new Node(15));
InsertNode(root, new Node(13));
InsertNode(root, new Node(11));
InsertNode(root, new Node(12));
InsertNode(root, new Node(25));
InsertNode(root, new Node(22));
InsertNode(root, new Node(23));
InsertNode(root, new Node(27));
InsertNode(root, new Node(26));
if(CheckIfTreeIsBalanced(root))
{
Console.WriteLine("Tree is Balanced!");
}
else
{
Console.WriteLine("Tree is Not Balanced!");
}
PrintTree(root);
}
public static void PrintTree(Node root)
{
if(root == null) return;
Node temp = root;
PrintTree(temp.leftNode);
System.Console.Write(temp.data + " ");
PrintTree(temp.rightNode);
}
public static bool CheckIfTreeIsBalanced(Node root)
{
if(root != null)
{
if(root.leftNode != null && root.rightNode!= null)
{
if(root.leftNode.data < root.data && root.rightNode.data > root.data)
{
return CheckIfTreeIsBalanced(root.leftNode)&&CheckIfTreeIsBalanced(root.rightNode);
}
else
{
return false;
}
}
else if(root.leftNode != null)
{
if(root.leftNode.data < root.data)
{
return CheckIfTreeIsBalanced(root.leftNode);
}
else
{
return false;
}
}
else if(root.rightNode != null)
{
if(root.rightNode.data > root.data)
{
return CheckIfTreeIsBalanced(root.rightNode);
}
else
{
return false;
}
}
}
return true;
}
public static void InsertNode(Node root, Node newNode )
{
Node temp;
temp = root;
if (newNode.data < temp.data)
{
if (temp.leftNode == null)
{
temp.leftNode = newNode;
}
else
{
temp = temp.leftNode;
InsertNode(temp,newNode);
}
}
else if (newNode.data > temp.data)
{
if (temp.rightNode == null)
{
temp.rightNode = newNode;
}
else
{
temp = temp.rightNode;
InsertNode(temp,newNode);
}
}
}
}
}
Output :
Hello, world!
Tree is Balanced!
10 11 12 13 15 20 22 23 25 26 27
I need to create a product catalog, in tree type.
every tree node presents by a ID(string), the functions on the tree data only 2:
getChild(string ID), give a ID, get children (no need include childrens'
children), if ID is null, get all root nodes
getParent(string ID), return parent ID if have, or null if is root
Since once the tree decided, will not change, so I think put all code in static will be best.
So I start to try use Dictionary
"id": {parent:ID, child:[id2, id3, id4....]}
Since theres about 1000+ catalog, I found I quickly mess myself up, lots of mistake in the static data, and make final result on usable. Also, now I only wrote dozens and the code is looking like mess.
Please advice a way create this simple catalog tree with high performance. Thanks
Just make a class out of it.
UPDATED:
class TreeNode : IEnumerable<TreeNode>
{
private readonly Dictionary<string, TreeNode> _children =
new Dictionary<string, TreeNode>();
public readonly string ID;
public TreeNode Parent { get; private set; }
public TreeNode(string id)
{
this.ID = id;
}
public TreeNode GetChild(string id)
{
return this._children[id];
}
public void Add(TreeNode item)
{
if (item.Parent != null)
{
item.Parent._children.Remove(item.ID);
}
item.Parent = this;
this._children.Add(item.ID, item);
}
public IEnumerator<TreeNode> GetEnumerator()
{
return this._children.Values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public int Count
{
get { return this._children.Count; }
}
}
Usage will be fairly simple to statically define:
var tree = new TreeNode("Root")
{
new TreeNode("Category 1")
{
new TreeNode("Item 1"),
new TreeNode("Item 2"),
new TreeNode("Item 3"),
},
new TreeNode("Category 2")
{
new TreeNode("Item 1"),
new TreeNode("Item 2"),
new TreeNode("Item 3"),
new TreeNode("Item 4"),
}
};
Edit
Some more functionality for even easier creation...
public static TreeNode BuildTree(string tree)
{
var lines = tree.Split(new[] { Environment.NewLine },
StringSplitOptions.RemoveEmptyEntries);
var result = new TreeNode("TreeRoot");
var list = new List<TreeNode> { result };
foreach (var line in lines)
{
var trimmedLine = line.Trim();
var indent = line.Length - trimmedLine.Length;
var child = new TreeNode(trimmedLine);
list[indent].Add(child);
if (indent + 1 < list.Count)
{
list[indent + 1] = child;
}
else
{
list.Add(child);
}
}
return result;
}
public static string BuildString(TreeNode tree)
{
var sb = new StringBuilder();
BuildString(sb, tree, 0);
return sb.ToString();
}
private static void BuildString(StringBuilder sb, TreeNode node, int depth)
{
sb.AppendLine(node.ID.PadLeft(node.ID.Length + depth));
foreach (var child in node)
{
BuildString(sb, child, depth + 1);
}
}
Usage:
var tree = TreeNode.BuildTree(#"
Cat1
Sub1
Item1
Item2
Item3
Sub2
Item1
Item2
Cat2
Sub1
Sub2
Item1
Item2
Sub3
Item1
Cat3
Cat4");
I created a Node class that could be helpfull. It is fast and has some extra properties, like:
Ancestors
Descendants
Siblings
Level of the node
Parent
Root
Etc.
You can write a simple binary tree , I wrote some Pseudo code beloew:
class TreeNode {
TreeNode Right;
TreeNode Left;
int id;
//...
}
class BinTree {
void Insert(TreeNode node)
{
while(true) {
if(node.id > target.id) {
if(target.Right != null) {
target = target.Right;
continue;
}
else {
target.Right = node;
break;
}
}
else if(node.id < target.id) {
if(target.Left != null) {
target = target.Left;
continue;
}
else {
target.Left = node;
break;
}
}
else {
throw new ArgumentException("Duplicated id");
}
}
}
TreeNode Search(int id)
{
TreeNode target = root;
while(target != null) {
if(id > target.id) {
target = target.Right;
}
else if(id < target.id) {
target = target.Left;
}
else {
return target;
}
}
return null;
}
}
But if your data count is very large, maybe AVL tree is more efficient