Binary trees FindParent method doesn't seem to work - c#

Here is my BNode class
class BNode
{
public int number;
public BNode left;
public BNode right;
public BNode(int number)
{
this.number = number;
}
}
And here is my implementation of FindParent method in BTree class
public BNode FindParent(BNode BNode, BNode searchNode)
{
if (searchNode.left == BNode || searchNode.right == BNode)
{
return searchNode;
}
if (searchNode.left != null)
{
return (FindParent(BNode, searchNode.left));
}
if (searchNode.right != null)
{
return (FindParent(BNode, searchNode.right));
}
return null;
}
Here is how i call it
BNode bnodeFound = btree.Find(18);
BNode bparent = btree.FindParent(bnodeFound, btree.rootNode);
It returns null always, except when the number is the first root from the trees root. What i also found trough debugging is that it goes to the left-most root, checks that it has no right root and then returns null. Have tried to figure out this, but to no success. I use similiar way to find a number in the tree, and that works for finding 18.

When you call FindParent() recursively each time for the left node (when it is not null), you are returning it directly which means the FindParent() for the right node will never be called.
// Assume we run this for the root node
if (searchNode.left != null)
{
// If left node is not null, then it tries to find in left subtree only
// Since it returns directly, whether found or not-found it WILL NOT
// search in right sub-tree
return (FindParent(BNode, searchNode.left));
}
// Unreachable code if left is not NULL
if (searchNode.right != null)
{
return (FindParent(BNode, searchNode.right));
}
To fix you can remove the return statement and instead check if it is still not found.
if (searchNode.left != null)
{
var found = (FindParent(BNode, searchNode.left));
// Return if found, else continue to check in right
if (found != null) return found;
}
// Checks in right sub-tree if not found in left subtree
if (searchNode.right != null)
{
// While checking in right sub-tree, then return irrespective of whether
// it was found or not found, since there aren't any more places to check
return (FindParent(BNode, searchNode.right));
}

Related

False if-statement still executes

I have the following method which should iterate through a tree while invoking actions on each node plus once every time it steps up or down the hierarchy. The logic itself works flawless, but I realized that my unit test fails because the if-statement which checks for already invoked elements fails to do what it is logical meant to do.
public static void IterateWithHierarchyFeedback(TBase start,
Func<TBase, IEnumerable<TBase>> childSelector,
Action<TBase> invoker,
Action stepUpInvocator,
Action stepDownInvocator,
bool invokeOnStart)
{
Stack<DynamicIterator> iterationStack = new Stack<DynamicIterator>();
iterationStack.Push(new DynamicIterator(start, childSelector(start).GetEnumerator()));
while (iterationStack.Count > 0)
{
var current = iterationStack.Pop();
// HERE it fails because current.Invoked = true but invoker() is still executed
if (!current.Invoked && invokeOnStart || current.Current != start)
invoker(current.Current);
if (current.Enumerator == null || !current.Enumerator.MoveNext())
{
if (current.Current != start)
stepUpInvocator();
continue;
}
stepDownInvocator();
current.Invoked = true;
iterationStack.Push(current);
iterationStack.Push(new DynamicIterator(current.Enumerator.Current,
childSelector(current.Enumerator.Current)?.GetEnumerator()));
continue;
}
}
This is my unit test:
[Test]
public async Task TestIterateWithFeedback()
{
StringBuilder b = new StringBuilder();
DynamicIterate<Tree>.Downwards.IterateWithHierarchyFeedback(_tree, t => t.Children,
tree => b.Append(tree.ReturnValue.ToString()),
() => b.Append('<'),
() => b.Append('>'),
true);
Assert.Warn(b.ToString());
const string expected = "1>2>3>4<>5<<>6<<>7>>";
Assert.AreEqual(expected, b.ToString());
}
And here you see that the output is not what it should be. That's because invoker() is called on elements that were already invoked, otherwise the output would be correct when it comes to order:
2) Expected string length 20 but was 23. Strings differ at index 8.
Expected: "1>2>3>4<>5<<>6<<>7>>"
But was: "1>2>3>4<3>5<3<2>6<2<>7<"
Can anyone explain to me why this happens? I found this but even without debugger it occurs. I also tried to change my state object (DynamicIterator) from struct to class (as I initially thought this might be an issue with the async variation. But that's not changing anything either.
I'm not sure that the problem is, but the iteration code looks more complicated than needed. I would propose something like this:
public static IEnumerable<(T Node, int Level)> DepthFirstWithlevel<T>(
T self,
Func<T, IEnumerable<T>> selector)
{
var stack = new Stack<(T Node, int Level)>();
stack.Push((self, 0));
while (stack.Count > 0)
{
var current = stack.Pop();
yield return current;
foreach (var child in selector(current.Node))
{
stack.Push((child, current.Level + 1));
}
}
}
This would return each node in the tree, together with the level in the tree the node has, with 0 being the root. If you specifically need methods to be called for each level change, you can make that with a separate method, something like this:
public static void IterateWithHierarchyFeedback<T>(
T self,
Func<T, IEnumerable<T>> selector,
Action<T> invoker,
Action stepUp,
Action stepDown)
{
int currentLevel = 0;
foreach (var (node, level) in DepthFirstWithLevel(self, selector))
{
while (currentLevel < level)
{
currentLevel++;
stepDown();
}
while (currentLevel > level)
{
currentLevel--;
stepUp();
}
invoker(node);
}
}
For the tree
A - B - C
| ⌞ D
⌞E - F
It will print A>E>F<B>DC, i.e. It will traverse the bottom branches first (insert a .Reverse() after selector(current.Node) to change this). And it will go from the F to B directly, without revisiting A.

How exactly is LinkedList<T> and LinkedListNode<T> implemented in C#? And how exactly does LinkedList<T>.Remove(LinkedListNode<T>) work?

I researched online that the inbuilt LinkedList is a Doubly LinkedList in C#. I also researched on the LinkedList.Remove(LinkedListNode) method. But I still couldn't find the answer to my question.
Following is the code snippet:
public string DequeueCat()
{
LinkedListNode<string> temp = animals.First;
while (temp != null && temp.Value.Contains("Cat") == false)
{
temp = temp.Next;
}
if (temp!=null && temp.Value.Contains("Cat"))
{
animals.Remove(temp);
return temp.Value;
}
else
{
Console.WriteLine("No more Cats available");
return null;
}
}
The variable animals is of type LinkedList<string>.
What exactly happens when we instantiate a fresh LinkedListNode<string> with animals.First? Such as LinkedListNode<string> temp = animals.First;.
Does a Deep Copy occur and, the original LinkedList (pointed by animals.First), gets copied over to temp, at a new location on the Heap?
Also, when we write animals.Remove(temp), the temp LinkListNode is destroyed. And, the corresponding value is removed from the animals LinkedList.
Following is the watch window before executing animals.Remove(temp) -
And, following is the Watch window AFTER executing animals.Remove(temp) -
My question is that, why is temp destroyed, after executing animals.Remove(temp)? Also, if temp has been created at a separate place on the Heap (as compared to the original LinkedList), then how do we know that Removing temp from the original, animals LinkedList will remove the corresponding item from
the animals LinkedList?
Following is the entire code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AnimalShelter
{
class AnimalsShelter
{
//This class will have the following functions:
//Enqueue, DequeueAny, DeQueueDog, DeQueueCat
//Implement queue using C# inbuilt linked list.
LinkedList<string> animals = new LinkedList<string>();
public void Enqueue(string animal)
{
animals.AddLast(animal);
}
public string DequeueAny()
{
LinkedListNode<string> firstAnimal = animals.First;
if (firstAnimal != null)
{
animals.RemoveFirst();
return firstAnimal.Value;
}
else
{
Console.WriteLine("No more animanls left in queue.");
return null;
}
}
public string DequeueDog()
{
LinkedListNode<string> temp = animals.First;
while(temp!=null && temp.Value.Contains("Dog")==false)
{
temp = temp.Next;
}
if(temp!=null && temp.Value.Contains("Dog"))
{
animals.Remove(temp);
return temp.Value;
}
else
{
Console.WriteLine("No more Dogs available");
return null;
}
}
public string DequeueCat()
{
LinkedListNode<string> temp = animals.First;
while (temp != null && temp.Value.Contains("Cat") == false)
{
temp = temp.Next;
}
if (temp!=null && temp.Value.Contains("Cat"))
{
animals.Remove(temp);
return temp.Value;
}
else
{
Console.WriteLine("No more Cats available");
return null;
}
}
}
class Program
{
static void Main(string[] args)
{
AnimalsShelter shelter = new AnimalsShelter();
shelter.Enqueue("Dog1");
shelter.Enqueue("Dog2");
shelter.Enqueue("Cat1");
shelter.Enqueue("Dog3");
shelter.Enqueue("Cat2");
shelter.Enqueue("Cat3");
Console.WriteLine(shelter.DequeueCat());
Console.WriteLine(shelter.DequeueAny());
Console.WriteLine(shelter.DequeueDog());
Console.WriteLine(shelter.DequeueCat());
Console.WriteLine(shelter.DequeueAny());
Console.WriteLine(shelter.DequeueAny());
}
}
}
Any light on this is highly appreciated. Thanks!
The variable animals is of type LinkedList<string>. What exactly
happens when we instantiate a fresh LinkedListNode<string> with
animals.First? Such as LinkedListNode<string> temp = animals.First;.
Does a Deep Copy occur
No. All you have done is copy a reference LinkedListNode<string> temp = animals.First;
Also, when we write animals.Remove(temp), the temp LinkListNode is
destroyed.
No. It's not being destroyed, however its linkages are being removed. It's still the same reference.
My question is that, why is temp destroyed, after executing
animals.Remove(temp)?
No. Once again it's not being destroyed. however its linkages are being removed.
Also, if temp has been created at a separate place on the Heap
No. It hasn't been created at a separate place on the heap, all you did is copy the reference.
then how do we know that Removing temp from the original, animals
LinkedList will remove the corresponding item from the animals
LinkedList
We know, because it was the same object / same reference.
Here is an approximation of the code for Remove. As you can see there is no magic:
internal void InternalRemoveNode(LinkedListNode<T> node)
{
...
if ( node.next == node)
head = null;
else
{
node.next.prev = node.prev;
node.prev.next = node.next;
if ( head == node)
head = node.next;
}
node.Invalidate();
count--;
version++;
}
Further Reading
Reference types (C# Reference)
There are two kinds of types in C#: reference types and value types.
Variables of reference types store references to their data (objects),
while variables of value types directly contain their data. With
reference types, two variables can reference the same object;
therefore, operations on one variable can affect the object referenced
by the other variable. With value types, each variable has its own
copy of the data, and it is not possible for operations on one
variable to affect the other (except in the case of in, ref and out
parameter variables; see in, ref and out parameter modifier).

'Sequence contains no elements', happening?

It's a WINDOWSFORM
I have combobox, I use this code for auto textboxvalue but I receive this error
Sequence contains no elements
private void cmbOfficeNumber_SelectedIndexChanged(object sender, EventArgs e)
{
using (UnitOfWork db = new UnitOfWork())
if (cmbOfficeNumber.SelectedValue.ToString() != null)
{
txtOfficeName.Text = db.OfficeRepository.GetOfficeNamebyNumber(cmbOfficeNumber.Text);
}
}
And this is my repository code
public string GetOfficeNamebyNumber(string officeNumber)
{
return db.Office.First(g => g.OfficeNumber == officeNumber).OfficeName;
}
EDIT: When using
return db.Office.FirstOrDefault(g => g.OfficeNumber == officeNumber).OfficeName;
I receive a different error
Object reference not set to an instance of an object
If First() results in
Sequence contains no elements
That means the condition in the lambda expression resulted in no hits. Because First requires you to have atleast one match.
If FirstOrDefault().Property results in
Object reference not set to an instance of an object
It means that the lambda expression resulted in no hits, and it returns a default value of the return type. In the case of a reference object it will be null. You then tried to access a property of null which causes the exception.
Simply put. Your problem is that your comparison is returning no hits.
You need to insert a fail safe for this to not crash
Something like:
public string GetOfficeNamebyNumber(string officeNumber)
{
var result = db.Office.FirstOrDefault(g => g.OfficeNumber == officeNumber);
if(result == null)
return string.Empty;
return result.OfficeName;
}
This can also be shortend to
public string GetOfficeNamebyNumber(string officeNumber)
{
var result = db.Office.FirstOrDefault(g => g.OfficeNumber == officeNumber);
return result?.OfficeName ?? string.Empty;
}
Or even
public string GetOfficeNamebyNumber(string officeNumber)
{
return db.Office.FirstOrDefault(g => g.OfficeNumber == officeNumber)?.OfficeName ?? string.Empty;
}
I hope this step by step explanation gives you the information you need to solve the problem.

check if list is null in c# method

hello to all i have this method
public void insertXmlNode(string XmlParentNodeName, List<string> XmlNodeName, List<string> XmlNodeValue, List<string> XmlAttributeName, List<string> XmlAttributeValue)
{
XmlDocument xdoc = new XmlDocument();
xdoc.Load(_connection);
XmlNode xparent = xdoc.SelectSingleNode("//" + XmlParentNodeName);
if (xparent == null)
{
xparent = xdoc.CreateNode(XmlNodeType.Element, XmlParentNodeName, null);
xdoc.DocumentElement.AppendChild(xparent);
}
for (int i = 0; i <= XmlNodeName.Count; i++)
{
XmlNode xnode = xdoc.CreateNode(XmlNodeType.Element, XmlNodeName[i], null);
xnode.InnerText = XmlNodeValue[i];
if (!string.IsNullOrEmpty(XmlAttributeName.ToString()))
{
XmlAttribute xattribute = xdoc.CreateAttribute(XmlAttributeName[i]);
xattribute.Value = XmlAttributeValue[i];
xnode.Attributes.Append(xattribute);
}
xparent.AppendChild(xnode);
}
xdoc.Save(_connection);
}
and i call this like below:
_db.insertXmlNode("Orders", _orderName, _orderValue, null, null);
"_db is a class instanc and _orderName & _orderValue has list string "
i wanna if XmlAttributeName not null add attribute to xml node but i
get this error
value can't be null
how i can check if XmlAttributeName not null do somthing?
Instead of doing the check this way, as you said in comment :
if (XmlAttributeName != null ||
XmlAttributeName.All(x => string.IsNullOrWhiteSpace(x)))
{
.......
}
Try to do it this way :
if (XmlAttributeName != null &&
XmlAttributeName.All(x => !string.IsNullOrWhiteSpace(x)))
{
.......
}
With && operator 2nd condition will only be checked if the 1st condition met. And code execution will enter if block, only if XmlAttributeis not null and all attributes in the list is not null or empty string.
private bool HasInvalidValues(IEnumerable<string> enumerable)
{
return enumerable == null || enumerable.Any(string.IsNullOrWhiteSpace);
}
The correct way to check for nullity is if(XmlAttributeName != null). This kind of check is ubiquitous for reference types; even Nullable<T> overrides the equality operator to be a more convenient way of expressing nullable.HasValue when checking for nullity.
If you do if(!XmlAttributeName.Equals(null)) then you will get a NullReferenceException if data == null. Which is kind of comical since avoiding this exception was the goal in the first place.
if (XmlAttributeName != null &&
XmlAttributeName.All(x => !string.IsNullOrWhiteSpace(x)))
{
// do here
}

C# Foreach-loop giving Null-error

I'm writing a bit of code, and there is a part that gives me hassles.
I'm having the following structure in my code:
foreach (Node node in nodes)
{
try
{
bool n = node.previous == null;
}
catch (Exception e)
{
StreamWriter s = new StreamWriter("error.txt");
s.WriteLine(e.Message);
s.WriteLine("-----------");
s.Close();
}
}
In here Node is a custom type, the node.prev variable is also a custom type (Location). Running this gives the following error-log:
Object reference not set to an instance of an object.
-----------
I'm 100% sure that node isn't null (which should be made impossible by foreach = Not true, sorry!). Also, as you can see in the following listing, the Node.previous is set to null at declaration:
public class Node
{
public Location previous = null;
public Location location;
public int distance;
...
...
}
I have no idea how I can fix these exeptions occuring, and I'm kind of at the end of having any ideas on how to solve this. Can anybody help me with this?
Note that these are all not the final code, but I sifted the parts that didn't matter!
Thanks in advance,
Delpee
EDIT: Ricovox helped me to the solution with this answer, thanks a lot!
So I'm posting another answer in response to your comment:
"I have checked for node being null, it isn't, at any point."
If that IS true, there here are some other options;
Take a look at the node.previous class/struct definition. It COULD implement a CUSTOM == operator that throws an error when compared to null. As an example, think about the Nullable<T> type. It has an overloaded == operator that returns true if the HasValue property is false (obviously, since it is a struct it isn't truly null, but overloading the operator gives the desired behavior.) To fix this, you could test object.ReferenceEquals(node.previous, null) which wouldn't be overloaded. If you have access to change the node.previous definition, perhaps you can find out why the overloaded operator throws an exception when compared to null (which it obviously shouldn't)
nodes could be null, in which case it is the foreach statement that is throwing the error. Test nodes == null before the foreach.
---------------Edit---------------
As Jeppe pointed out, my analogy with Nullable<T> (in option #1, above) could be misleading (in fact it did confuse the discussion, although the point itself was correct). In order to better illustrate the idea of overriding the == operator, I've posted an example below that demonstrates the Container type. This type is a struct, so it can never be null itself, but it contains a single Value object.
(The point of this struct is that you can work with any Container object without worrying whether or not it is null, even though the contained Value object might be null). The main thing to note is that when a Container is compared with == to null, the result will be true if Value is null, which would NOT be true if the == operator weren't overridden (because a struct can never be null).
public struct Container {
public object Value { get; set; }
public bool IsNull { get { return Value == null; } }
public static bool operator ==(Container x, object y) { return x.Equals(y); }
public static bool operator !=(Container x, object y) { return !x.Equals(y); }
public override bool Equals(object obj) {
if (obj is Container)
return Value == ((Container)obj).Value;
return Value == obj;
}
public override int GetHashCode() { return Value == null ? 0 : Value.GetHashCode(); }
}
////---------Test----------
var x = new Container { Value = null };
var y = new Container { Value = "hi" };
var z = new Container { Value = null };
Print(x == null); //true
Print(x == y); //false
Print(x == z); //true
And just in case you are wondering how overriding == would affect a class, I've written another example below that demonstrates a Box class. It's similar to the Container struct, except that we have to deal with the case in which the Box object is null itself. Note that in this case, there is another surprising result of overriding ==. Two reference types can be equal (==) to each other, even if they reference different objects, as long as they have equal Value properties.
public class Box {
public static bool ItemsEqual(object x, object y) {
object xval, yval;
xval = x is Box ? (x as Box).Value : x;
yval = y is Box ? (y as Box).Value : y;
return xval == yval;
}
public object Value { get; set; }
public bool IsNull { get { return Value == null; } }
public static bool operator ==(Box x, object y) { return ItemsEqual(x, y); }
public static bool operator !=(Box x, object y) { return !ItemsEqual(x, y); }
public override bool Equals(object obj) { return ItemsEqual(this, obj); }
public override int GetHashCode() { return Value == null ? 0 : Value.GetHashCode(); }
}
////---------Test----------
object n = null;
Box w = null;
Box x = new Box { Value = null };
Box y = new Box { Value = "hi" };
Box z = new Box { Value = "hi" };
Print(w == null); //true (uses overridden '==' because w is defined as a Box)
Print(w == n); //true
Print(x == w); //true
Print(x == null); //true
Print(x == n); //true
Print(w == y); //false
Print(x == y); //false
Print(y == z); //true (actual ref's differ, but values are ==)
The most likely problem is that node is null!. There is nothing about the foreach statement that would prevent node from being null, because in general an IEnumerable object (e.g. a list or collection) CAN contain null as a valid item.
No error would be thrown if previous is null (unless the node.prev class/struct overrides the == operator).
As others have mentioned, put in a test like this to verify:
foreach (Node node in nodes)
{
bool n;
try
{
if (node == null)
{
n = true; //do something to deal with a null node
}
else
{
n = node.previous == null;
}
}
catch (Exception e)
{
StreamWriter s = new StreamWriter("error.txt");
s.WriteLine(e.Message);
s.WriteLine("-----------");
s.Close();
}
}
If nodes were null the exception would occur before the loop, and the exception wouldn't be caught.
Since the previous member is a simple field, the only possibility I see is that one of the node members of your nodes collection is null. You can do this:
foreach (Node node in nodes)
{
if (node == null)
throw new Exception("I told you so");
}
EDIT: OK, it turned out there was one possibility I didn't see, and that was a broken overload of the == operator. To make sure you call the usual overload, say:
foreach (Node node in nodes)
{
bool n = (object)(node.previous) == (object)null;
}
(actually it will suffice to cast just one side of the == operator to object), or equivalently use ReferenceEquals:
foreach (Node node in nodes)
{
bool n = object.ReferenceEquals(node.previous, null);
}
But you must fix the wrong implementation of the == overload.
If you had posted the stack trace of the exception in your original question, it would have been clear to most users here on SO that the exception came from a call to your == overload. So next time, inspect your stack trace.
set a breakpoint at your line that starts with bool and verify that node is not null and that nodes is not null. My guess is that either nodes is null, or else it contains a null value if it's not a type-safe list.
There's nothing that ensures that node is not null, since Node is not a value type. Mind giving more details?
I'm 100% sure that node isn't null
But I'm 100% sure that an element in nodes is null! try this:
foreach (Node node in nodes)
{
try
{
if(null == node) throw new Exception("This is not expected!");
bool n = node.previous == null;
}
catch (Exception e)
{
if(File.Exists("error.txt")) File.Delete("error.txt");
using(StreamWriter s = new StreamWriter("error.txt")){
s.WriteLine(e.Message);
s.WriteLine("-----------");
s.Close();}
}
}

Categories

Resources