How to handle parameters right in c#? - c#

I just started using c# again and now I have a strange problem with my parameters.
I tried to build a List by my self.
So I have:
class NodeList
{
public Node FirstCity { get; set; }
public Node findNode(String name)
{
//...stuff
}
}
And This:
class Node
{
public String Name {get; set;}
public Node next {get; set;}
}
So, in my project I (lets say on button click) create a new Nodelist.
(By default I have already a few nodes in it.)
Now I do this:
Node n = nodelist.findNode("test");
and then I have another class I called tool.
tool.doSomething(n , nodelist);
Now the strange thing is that, when I look at nodelist, when I call the above the list is correct. The doSomething method, doesn´t even call the nodelist but it changes it.
doSomething(n, list)
{
NodeList nl = new NodeList();
nl.Add(n);
//other stuff
}
At the point where I change the new List for some reason the other list, which is in a different class, changes too.
Can anyone please explain why and how I can fix this!?
Edit:
This is my Add Method:
Add(Node node){
node.next = null;
Node current = FirstCity;
if (current == null)
FirstCity = node;
else
{
while (current.next != null)
{
current = current.next;
}
current.next = node;
}
}

Related

singly linked list in c# using extension method

why extension method does not return the modified node in Insertion operations.
But It Working Fine at the time of Linked list Creation.
Extension method should return the modified Node.
What is the perfect way to do this.
IS extension method good in performance
Code follows
public class Node
{
public Object Data { get; set; }
public Node NextNode { get; set; }
}
public static class ListOperations
{
public static void CreateLinkedList(this Node node, Object data)
{
if (node.Data == null)
{
node.Data = data;
}
else
{
Node newnode = new Node();
newnode.Data = data;
Node current = new Node();
current = node;
while (current.NextNode != null)
{
current = current.NextNode;
}
current.NextNode = newnode;
node = current;
}
}
public static void InsertNode(this Node node1, Object data, int position)
{
Node newnode = new Node();
newnode.Data = data;
if (position == 1)
{
newnode.NextNode = node1;
node1 = newnode;
}
}
}
class Program
{
static void Main(string[] args)
{
Node node = new Node();
//random Singly LinkedList
node.CreateLinkedList(10);
node.CreateLinkedList(11);
node.CreateLinkedList(12);
node.CreateLinkedList(13);
node.CreateLinkedList(14);
node.CreateLinkedList(15);
node.InsertNode(20, 1);// this method does not return node value what is inserted.
}
}
There are many things wrong with your code, and we can deal with them later. But let's answer your questions first. I will be a bit literal and direct, since I can't assume why you have done it the way it is done.
why extension method does not return the modified node in Insertion operations.
Since your method doesn't return anything
But It Working Fine at the time of Linked list Creation.
Yes, since that code doesn't ever modify the this Node node parameter
Extension method should return the modified Node.
Only if you actually return any data from the method!
What is the perfect way to do this.
See below
IS extension method good in performance
Extension method compared with what? Compared with member method written similarly, there should really be no performance difference in the cases relevant to your example
Perfect way to do it:
So first things first: There is no need to write an extension method here. Why wouldn't you write a regular member method? Extensions are usually done when the class you want to add the functionality is not directly available for you to edit, typically as the code belongs to a third party
Second, you don't quite seem to understand the references and how the pass-by-value works. First let me post a better code, and then explain it
public class Node {
public object Data { get; set; }
public Node NextNode { get; set; }
public Node(object data) {
Data = data;
}
public Node AppendNode(object data) {
var newNode = new Node(data);
var current = this;
while (current.NextNode != null)
current = current.NextNode;
current.NextNode = newNode;
return newNode;
}
public Node SetFirstNode(object data) {
return new Node(data) { NextNode = this };
}
}
class Program {
static void Main(string[] args) {
var linkedList = new Node(10);
linkedList.AppendNode(11);
linkedList.AppendNode(12);
linkedList.AppendNode(13);
linkedList.AppendNode(14);
linkedList.AppendNode(15);
linkedList = linkedList.SetFirstNode(20);
}
}
The important things to notice from the perspective of your main question (why the insert did not work) is that the method SetFirstNode actually returns the newly created node and in Main, we re-assign the linkedlist as such linkedList = linkedList.SetFirstNode(20);
Now, you can actually write a static method and pass by ref the linkedlist, but that is not a good practice, in my opinion. Nevertheless, the code would look like below
public static class ListOperations {
public static void InsertNode(ref Node linkedList, object data) {
linkedList = new Node(data) { NextNode = linkedList };
}
}
Among other things to notice, I am calling the node object as linkedList, CreateLinkedList as AppendNode and InsertNode as SetFirstNode on purpose, so you can understand the code better.
Below is the same code with generic argument instead of object Data and using a proper InsertNode method
public class Node<T> {
public T Data { get; set; }
public Node<T> Next { get; set; }
public override string ToString() {
return Data.ToString();
}
public Node(T data) {
Data = data;
}
public Node<T> AppendNode(T data) {
var newNode = new Node<T>(data);
var current = this;
while (current.Next != null)
current = current.Next;
current.Next = newNode;
return newNode;
}
/// <summary>
/// Inserts a new node into the linkedlist as the desired position
/// </summary>
/// <param name="position">0-based index for the final position of new node</param>
/// <param name="newNode">The newly created node containing data</param>
/// <returns>returns the first node of the linkedlist</returns>
public Node<T> InsertNode(T data, int position, out Node<T> newNode) {
var current = this;
position--;
newNode = new Node<T>(data);
if (position < 0) {
newNode.Next = current;
return newNode;
}
for (int i = 0; i < position; ++i)
current = current.Next;
newNode.Next = current.Next;
current.Next = newNode;
return this;
}
}
class Program {
static void Main(string[] args) {
var linkedList = new Node<int>(10);
linkedList.AppendNode(11);
linkedList.AppendNode(12);
linkedList.AppendNode(13);
linkedList.AppendNode(14);
linkedList.AppendNode(15);
linkedList = linkedList.InsertNode(20, 0, out var newNode);
}
}

C# Putting non-hierarchical CSV data into hierarchy

We have a 3rd party workflow system that contains a hierarchical list of actions which is stored as flat file in the following format:
Root
Root-Node1
Root-Node1-Node1
Root-Node1-Node2
Root-Node1-Node2-Node1
Root-Node1-Node2-Node1-Node1
Root-Node1-Node2-Node1-Node2
Root-Node2
Root-Node2-Node1
etc...
Under each node is a list of properties and the aim of this project is to write a small program that will iterate through each file, build a hierarchy from the Root-Node relationships and then we will able to use this model to run reports on the data.
My attempt so far has been to create a Node class, containing a Child property of type List<Node> which will store the hierarchy
I am struggling to figure out how to determine which Node should be the child of which node. My current process is to capture the previous node name and if the current node name contains the previous node name, it must be a child, but I found this to be flakey when it gets a few nodes deep.
Does anyone have any suggestions for a more reliable way to describe these relationships?
Something like this should work:
public class Node
{
public string Key { get; set; }
public Node Parent { get; set; }
public IList<Node> Children { get; set; }
}
private Node LoadAll(string[] keys)
{
var nodes = new Dictionary<string, Node>(StringComparer.OrdinalIgnoreCase);
var orphanNodes = new List<Node>();
Node root = null;
foreach (var key in keys)
{
var node = new Node()
{
Key = key
};
nodes[key] = node;
int keySeparator = key.LastIndexOf("-");
if (keySeparator != -1)
{
string parentKey = key.Substring(0, keySeparator);
if (nodes.TryGetValue(parentKey, out var parentNode))
{
if (parentNode.Children == null)
{
parentNode.Children = new List<Node>();
}
node.Parent = parentNode;
parentNode.Children.Add(node);
}
else
{
orphanNodes.Add(node);
}
}
else if (root != null)
{
throw new Exception("Root node already exists.");
}
else
{
root = node;
}
}
foreach (var orphan in orphanNodes)
{
string parentKey = orphan.Key.Substring(0, orphan.Key.LastIndexOf("-"));
if (nodes.TryGetValue(parentKey, out var parentNode))
{
if (parentNode.Children == null)
{
parentNode.Children = new List<Node>();
}
orphan.Parent = parentNode;
parentNode.Children.Add(orphan);
}
else
{
throw new Exception("Nodes without parents found.");
}
}
return root;
}
It maintains a list of all nodes (nodes) with their keys, so that any node can easily be looked up form its key. It also maintains a list of nodes for which we didn't have any parents for on the initial loop run through (orphanNodes - you can remove this if your parent nodes always come before your child nodes).
For each key we:
Create an instance of node
Extract the parent key
If there is no parent key, assume it's the root element
Try to locate the parent node. If it's found, add the current node as a child. If it isn't found, add the current node as an orphan.
In case any parent nodes were loaded after their children, we then do the following for every orphan:
Extract the parent key.
Try to locate the parent node. If it's found, add the current node as a child. If it isn't found, throw an error.
Some of the string manipulation could maybe be improved, but this is a way you could approach the situation.

setting reference of an object to null seems to not work

I am trying to delete a node from a binary tree using c#. This example only works if the node has no children. I understand how the deletion works with children, but I'm getting hung up on an issue that seems to me to be from a lack of understanding of c#:
public class Tree
{
internal class Node
{
public int Val { get; set; }
public Node Left { get; set; }
public Node Right { get; set; }
public Node(int val)
{
Val = val;
}
}
private Node root;
public void Delete(int val)
{
Node current = this.root;
Node parent = null;
while (true) {
if (val < current.Val) {
parent = current;
current = current.Left;
}
else if (val > current.Val) {
parent = current;
current = current.Right;
}
else if (val == current.Val) {
current = null;
return;
}
}
}
}
My issue is in the line where I set current = null. The way I'm intending to use this, is to use current = null to delete the current node. But it doesn't work. if I reference the current node from the parent:
parent.Right = null;
the node is properly deleted, but is obviously a pain because I need to check if the current node is the right or left child of the node. What am I missing? Thanks in advance!
You cannot do this.
The current variable is a separate variable from the parent.Left or parent.Right variables.
When you do this:
current = parent.Left;
you're copying the value of the variable, you're not linking one variable to another. You can liken this to postit notes. On one postit note you have an address, then you execute the above statement and copy the address onto another postit note. Changing the copy afterwards does not in any way or shape change the original note.
So yes, you need to keep track of which child reference variable you got current from.

Counting descendants in a tree

I have the following class which recurs on itself to form a tree-like data structure:
public class chartObject
{
public string name { get; set; }
public int descendants { get; set; }
public List<chartObject> children { get; set; }
}
For each object in the tree I would like to populate the descendant property with the amount objects that exist underneath it.
Example structure:
chartObject1 (descendants: 4)
└-chartObject2 (descendants: 0)
└-chartObject3 (descendants: 2)
└--chartObject4 (descendants: 1)
└---chartObject5 (descendants: 0)
What would be the most efficient way of doing this?
How about the recursive formula:
children.Count + children.Sum(c => c.descendants)
This is suitable for eager-evaluation / caching if the tree is immutable (which it isn't from the class declaration). If you want efficiency even in the face of mutability, you'll find this a lot more difficult; you can consider marking parts of the tree "dirty" as it is mutated / eagerly force the re-evalutation of this metric to "bubble up" as part of a tree is mutated.
This works for me:
public void SetDescendants(chartObject current)
{
foreach (var child in current.children)
{
SetDescendants(child);
}
current.descendants = current.children.Sum(x => 1 + x.descendants);
}
I tested with this code:
var co = new chartObject()
{
name = "chartObject1",
children = new List<chartObject>()
{
new chartObject()
{
name = "chartObject2",
children = new List<chartObject>() { }
},
new chartObject()
{
name = "chartObject3",
children = new List<chartObject>()
{
new chartObject()
{
name = "chartObject4",
children = new List<chartObject>()
{
new chartObject()
{
name = "chartObject5",
children = new List<chartObject>() { }
}
}
}
}
}
}
};
And got this as the result:
For calculations to be most efficient, cache their result in the node itself. Otherwise, you'll be re-calculating the count every time the descendants property is looked up.
The cost of doing that is the need to invalidate the cache all the way up the parent chain, like this:
public class chartObject
{
private chartObject _parent;
private int? _descCache = null;
public string name { get; set; }
public int descendants {
get {
return _descCache ?? calcDescendents();
}
}
public List<chartObject> children { get; set; }
public void AddChild(chartObject child) {
child._parent = this;
children.Add(child);
chartObject tmp = this;
while (tmp != null) {
tmp._descCache = null;
tmp = tmp._parent;
}
}
private int calcDescendents() {
return children.Count+children.Sum(child => child.descendants);
}
}
Walk all nodes of the tree (depth first is ok) and when done with children set "descendants property to sum of children's descendants + child count. You have to do it on every change to the tree structure. You should be able to limit updates only to parents of element that is changed.
If nodes made immutable you can populate the field at creation time.
Side notes:
Your tree is mutable as it is now (one can easily add more child nodes anywhere), so it may be safer to have method that counts descendants instead of property on a node.
Having computed property int descendants { get; set; } to be read/write is confusing as anyone can set its value to whatever number. Consider if making it read only and updating when one of child nodes changes (requires some custom notification mechanism).
Code style - consider naming classes with upper case names for code that is intended to be public (follow Microsoft's C# coding guidelines). chartObject -> ChartObject

Simple Linked List C# AddAfter method

Im working with simple linked lists in C# and I have no idea how to add elements at the end of the list, colud anyone helpme?
namespace ConsoleApplication1
{
class Class1
{
public class Node()
{
public int Data;
public Node Next;
}
private Node FirstNode=null;
public void AddBefore(int number)
{
Node NewNode=new Node();
NewNode.Next=FirstNode;
NewNode.Data=number;
FirstNode=NewNode;
}
public void AddAfter(int number)
{
if (FirstNode==null)
{
AddBefore(number);
}
else
{
???????????????
}
}
}
}
You need to iterate through your list until you find the last node, and then add it to the end. Something like:
public void AddAfter(int number)
{
if (FirstNode==null)
{
AddBefore(number);
}
else
{
// Finding the last node
Node currentNode = FirstNode;
while (currentNode.NextNode != null)
currentNode = currentNode.NextNode;
// Constructing a new node
Node newNode = new Node();
newNode.Data = number;
newNode.Next = null;
// Adding the new node to the end
currentNode.NextNode = newNode;
}
}
else
{
Node NewNode=new Node();
NewNode.Data=number;
Node LastNode = GetLastNode();
LastNode.Next = NewNode;
}
You'll still have to implement GetLastNode or else you wont practise anything =P
The question is kind of confusing. Are you asking how to place a node at the end of the list, or as the next item in the list.
I had to do this for a homework assignment way back in the day (it was java though). If you want to always add a node to the end of the list then you also need to edit your list class to contain a head and tail of the list. This will allow you to add items to the end or beginning.
If you want to always add a node to the end then you could try editing the code so that when you add a node to the end the previous node's next node value will be set to the tail instead of null. This will always allow for you to add an item to the end of the list (which is what most add methods do unless a position is specified anyways)
In short:
Add Node tailNode = null; to Class and add a method that will get and set the next node for the Node class. Once this is done, then edit the code so that it looks something like this:
class Class1
{
public class Node()
{
public int Data;
public Node Next;
//Class to set next node
public void setNext(Node nextNode)
{
//Set next node
Next = nextNode;
}
//Get next node
public Node getNext()
{
return Next;
}
}
private Node FirstNode=null;
private Node lastNode = null;
public void AddBefore(int number)
{
Node NewNode=new Node();
NewNode.Next=FirstNode;
NewNode.Data=number;
FirstNode=NewNode;
}
public void AddAfter(int number)
{
if (FirstNode==null)
{
AddBefore(number);
}
else
{
if(FirstNode.getNext() == null)
{
//No tail. Make this node tail
lastNode = new Node();
lastNode.Data = number;
//Set first node's next to last node
FirstNode.setNext(lastNode);
}else{ //TailNode already set
//New node to be tail
Node newLastNode = new Node();
newLastNode.Data = number;
//Set the current tail node to have this node as next
lastNode.setNext(newLastNode);
//Make new last node last node
lastNode = newLastNode;
}
}
}
}
The code may be a little off (I haven't really tested it) but that is the main picture of what you are going to have to do.

Categories

Resources