Undestanding Basic LinkedList - c#

I'm trying to wrap my head around linked lists and I have this code sample here:
public class SinglyLinkedListNode {
public int data;
public SinglyLinkedListNode next;
public SinglyLinkedListNode(int data) {
this.data = data;
this.next = null;
}
public void Print() {
Console.WriteLine(data);
if(next != null) {
next.Print();
}
}
}
public class SinglyLinkedList {
public SinglyLinkedListNode headNode;
public SinglyLinkedList() {
headNode = null;
}
public void Print() {
if(headNode != null) {
headNode.Print();
}
}
}
class Program {
static void Main(string[] args) {
SinglyLinkedList list = new SinglyLinkedList();
int listCount = 5;
for(int i = 0; i < listCount; i++) {
int listItem = i + 1;
SinglyLinkedListNode list_head = InsertNodeAtTail(list.headNode, listItem);
list.headNode = list_head;
}
list.Print();
}
static SinglyLinkedListNode InsertNodeAtTail(SinglyLinkedListNode head, int data) {
if (head == null) {
head = new SinglyLinkedListNode(data);
return head;
} else {
var temp = head;
while (temp.next != null) {
temp = temp.next;
}
temp.next = new SinglyLinkedListNode(data);
return head;
}
}
}
in the InsertNodeAtTail method in the else statement where it's basically storing the passed in headNode as a temp variable and at the very end of it it set the temp variables next pointer to the new data were passing in and then return head. In this scenario how does head track the changes in the temp variable?
When I debug this and check the return head value it has all the changes that I've done to the temp variable but the head value was never really modified/used besides the part where it's being assigned to the temp variable.
Example is let's say we got a list 1 -> 3 -> 5 -> and were adding in 6
6 gets added into the temp.next and on return head, the head value contains 1 -> 3 -> 5 -> 6 but we've never done anything to head? All changes were to the temp variable.
Sorry if this might be a stupid question but I'm just not getting how this works.
Thanks

When I debug this and check the return head value it has all the changes that I've done to the temp variable but the head value was never really modified/used besides the part where it's being assigned to the temp variable.
temp is a reference to an SinglyLinkedListNode.
When you call the following code it keeps changing the reference of temp to the next SinglyLinkedListNode in the chain until you reach the last node. At this point temp is referring to the 5 in your example, and appends your new 6 to the end. No change is made to the head.
Since it is a chain 1 -> 3 -> 5, adding 6 to the end affects the whole chain and now becomes 1-> 3 -> 5 -> 6.
var temp = head;
while (temp.next != null) {
temp = temp.next;
}

Related

Understanding C# class behavior in recursive programming

There is a ListGenerator that accepts an array of int and turns it into a recursive object.
public class ListNode
{
public int val;
public ListNode next;
public ListNode(int x) { val = x; }
public ListNode(int val = 0, ListNode next = null)
{
this.val = val;
this.next = next;
}
}
public static ListNode GenerateList(int[] nums)
{
if (nums == null || nums.Length == 0) { return null; }
var i = 0;
var first = new ListNode(nums[i]);
var current = first;
while (++i < nums.Length)
{
current.next = new ListNode(nums[i]);
current = current.next;
}
return first;
}
I know that classes in C# are reference type so after executing this line of code current.next = new ListNode(nums[i]); the value of first variable will change same as current and everything is good.
But after current = current.next; the value of first and current are not same. Actually, the next property has a value in the first but it is null in the current.
I don't understand why that is. In my view, first must be the same as current but it is not.
With var current = first; you copy the reference in first to current. At that point they refer to the same object. Any change in current.next is visible in first.next.
Later you reassign current, so now that is pointing to something other that first. The reference in first in not affected.

Remove the biggest value from a linked list

So I've said it in the title, I want to delete the biggest value from a LinkedList, can't get my head around how to exactly do it. I tried this but I get an error.
//Remove n from list 'first'
public static void Remove(Node<int> first, Node<int> n)
{
Node<int> pos = first;
while (pos.GetNext() != n)
pos = pos.GetNext();
pos.SetNext(n.GetNext());
}
public static void DeleteMaxValue(Node<int> first)
{
int max = 0;
Node<int> pos = first;
Node<int> maxNode = null;
while(pos.GetNext() != null)
{
if (pos.GetNext().GetValue() > max)
{
maxNode = new Node<int>(pos.GetNext().GetValue());
}
pos = pos.GetNext();
}
Remove(first, maxNode);
}
imagine this is your Node structure in linked list
public class Node
{
public int data;
public Node next;
}
you can use this function to find the biggest number in the linked list and then remove it.
public int GetMax(Node head)
{
int max = int.MinValue();
while(head != null)
{
if(max < head.data)
max = head.data;
head = head.next;
}
return max;
}
Several issues:
max is never updated. It should be updated when you have found a greater value, otherwise the last positive value is considered the greatest.
maxNode is never a node that is in the list, since it is created as a new node. By consequence the Remove function will not find it and nothing gets deleted.
Your function's signature has no way of deleting the first node, since first is passed by value. There is no way to solve this for all cases, unless you change the design:
Either let first be a member of your class, and then don't pass it as argument, or
Let the function return the (potentially) new value of first, so the caller can adapt its own reference to the head of the list.
max = 0 assumes that your list cannot have negative values. In case this is possible, I would suggest initialising max with the value that is in the first node (after having checked that the list is not empty).
Instead of cycling again through the list with Remove, keep a reference to the node the precedes the node that is to be deleted.
Here is a function that returns the value of first, so the caller can make an update to their own reference in case the first node was deleted:
// Return type changed: the function will return the first node
public static Node<int> DeleteMaxValue(Node<int> first)
{
if (first == null) { // In an empty list there is nothing to delete
return;
}
int max = first.GetValue(); // Don't use 0, values might be negative
Node<int> pos = first;
Node<int> maxNode = first;
Node<int> beforeMaxNode = null; // Have a reference that lags behind
while(pos.GetNext() != null)
{
int val = pos.GetNext().GetValue();
if (val > max)
{
max = val; // Update max
beforeMaxNode = pos; // Don't create a new node
}
pos = pos.GetNext();
}
if (beforeMaxNode == null) { // First node has the maximum
// Now `first` reference will change, so it's important to return
// that new reference, else the caller will not see any change
first = maxNode.GetNext();
} else {
beforeMaxNode.SetNext(maxNode.GetNext());
}
return first;
}

Trying to remove value from class

I've been trying to remove manually entered value from 'Solmu' class after changing it to integer.
private static void PoiataTiettyArvo(ref Solmu lista)
{
Console.WriteLine("Anna arvo jonka haluat poistaa: ");
int PoistaMinut = int.Parse(Console.ReadLine());
int arvo = Convert.ToInt32(lista.data);
if(PoistaMinut != null)
{
arvo.RemoveAt(PoistaMinut);
}
}
My Solmu class is defined like this:
public class Solmu
{
public Solmu next;
public Solmu prev;
public double data;
}
Seems RemoveAt does not work with this, any alternatives?
Based on your comment, this looks like a linked list. You'll have to loop through your values to find the node to delete (this code is untested):
private static void PoiataTiettyArvo(ref Solmu lista)
{
Console.WriteLine("Anna arvo jonka haluat poistaa: ");
int PoistaMinut = int.Parse(Console.ReadLine());
var previousNode = null;
var currentNode = lista;
while (currentNode != null)
{
int arvo = Convert.ToInt32(lista.data);
if (PoistaMinut == arvo)
{
if (previousNode == null)
{
// If there was no previous node, the head of the list is being deleted.
// update lista
lista = currentNode;
}
else
{
previousNode.next = currentNode.next;
if (currentNode.next != null)
{
currentNode.next.prev = previousNode;
}
}
break;
}
previousNode = currentNode;
currentNode = currentNode.next;
}
}
Updated Answer:
Okay, now I understand what you're trying to do. You're going through a linked list to remove an item that matches the item that the user enters.
Option 1) If your Solmu class has an implementation of RemoveAt, you can call it as I posted below - however, RemoveAt methods typically expect an index value, so I would call it Remove (or something more specific like RemoveValue).
Option 2) If your Solmu class is self-created, you will need a loop that starts with the head value and compares the data field to the user-entered value, and remove it.
(Removed my code in favor of Jacob's.)
Original answer:
You're not removing anything from lista. Your code:
int PoistaMinut = int.Parse(Console.ReadLine());
int arvo = Convert.ToInt32(lista.data);
if(PoistaMinut != null)
{
arvo.RemoveAt(PoistaMinut); // <- Remove an int from an int?
}
is trying to remove something from arvo.
You should modify your code to say
lista.RemoveAt(PoistaMinut);
instead.
(In that case, however, I wonder what purpose arvo serves. Can you elaborate?)

C# ArrayList.Add() overwriting previous objects on add

I have written a simple method that receives a Generic that I wish to place into an ArrayList using the ArrayList.Add() method. However I have discovered that when I go add a new item with the same type as previous items in the ArrayList this new item overwrites the previous items individual properties.
Here's the code its pretty basic and rather embarrassingly I can't seem to rectify this overwriting problem.
public class ChromosomeTree<T>
{
private GeneNode<T> root;
private ArrayList children = new ArrayList();
private int depMax;
string stemp;
public ChromosomeTree()
{
root = null;
}
public virtual void Clear()
{
root = null;
}
public GeneNode<T> Root
{
get
{
return root;
}
set
{
root = value;
}
}
public int MaxDepth
{
get
{
return depMax;
}
set
{
depMax = value;
}
}
public ArrayList Children
{
get
{
return children;
}
}
public GeneNode<T> lastChild()
{
return (GeneNode<T>)this.Children[this.Children.Count - 1];
}
public void addFull(GeneNode<T> node)
{
//check if the chromosome tree has a root if not add the first node as the chromosomes root
if (this.Root == null)
{
this.Root = node;
children.Add(node);
stemp += " " + node.Value;
}
else
{
for (int i = 0; i <= this.Children.Count - 1; i++)
{
GeneNode<T> parent = (GeneNode<T>)this.Children[i];
//check to ensure maxDepth of chromosome tree is not exceeded
if (parent.Depth != this.MaxDepth)
{
//check to see if the current node stil has room for another node to be added to it
if ((parent.Children == null) || (parent.Children[1] == null))
{
children.Add(node);
parent.Add(node);
stemp += " " + node.Value;
break;
}
}
else
{
break;
}
}
}
}
public override string ToString()
{
string chromosome = String.Empty;
foreach(GeneNode<Gene> gene in this.Children)
{
chromosome += " " + gene.Value.GeneValue.ToString();
}
return chromosome;
}
}
Im pretty sure its a simple mistake but ive looked at this for so long I cant see the wood from the trees. Any thoughts would be greatly appreciated.
Many thanks in advance.
Luke
here is the code that utilises the this class.
EDIT : THE OVERWRITE HAPPENS WHEN THE METHOD IS CALLED NOT AFTER THE METHOD HAS EXECUTED ITS LOGIC
class SimpleChromosome
{
Random rand = new Random();
Gene funcGene = new Gene();
Gene termGene = new Gene();
private string sChromosome;
private int currentdepth;
private string grownChromosome()
{
return sChromosome;
}
public ChromosomeTree<Gene> fullChromosome()
{
ChromosomeTree<Gene> chromosone = new ChromosomeTree<Gene>();
//chromosone.MaxDepth = rand.Next(1, 5);
chromosone.MaxDepth = 1;
int maxGenes = (int)Math.Pow(2, chromosone.MaxDepth + 1) - 1;
for (int i = 0; i <= chromosone.MaxDepth; i++)
{
int numNodesForLevel = (int)Math.Pow(2, i);
int numNodesOnLevel = 0;
for (int j = 0; j < numNodesForLevel; j++)
{
if (currentdepth != chromosone.MaxDepth)
{
funcGene.GenerateValue(GeneType.Function);
GeneNode<Gene> geneNode = new GeneNode<Gene>(funcGene);
sChromosome += " " + geneNode.Value;
chromosone.addFull(geneNode);
numNodesOnLevel++;
}
else
{
termGene.GenerateValue(GeneType.Terminal);
GeneNode<Gene> geneNode = new GeneNode<Gene>(termGene);
sChromosome += " " + geneNode.Value;
chromosone.addFull(geneNode);
numNodesOnLevel++;
}
if ((numNodesForLevel == numNodesOnLevel) && (currentdepth != chromosone.MaxDepth))
{
currentdepth++;
}
}
}
currentdepth = 0;
//Console.WriteLine("Before ADD :" + sChromosome);
sChromosome = "";
return chromosone;
}
}
Post the code where you are adding a new object of this type to your ArrayList.
My guess is that you are using two references to the same object.
Remember that objects are reference types, therefore if you assign them to each other you are only assigning their references. e.g. in the following code:
Foo foo1 = new Foo();
foo1.x = 1;
Foo foo2 = new Foo();
foo2.x = 2;
foo2 = foo1; // foo2 now points to the same object as foo1;
// foo1.x does not get copied into foo2.x.
// You have also lost your reference to the original foo2 object here and it will be garbage collected.
foo2.x = 100;
// since foo2 and foo1 are now pointing to the same object. both foo2.x and foo1.x will be 100
For this sort of relationship you really should be coding to interfaces. eg.
public interface IGeneNode{
//genenode definition including perhaps equality interfaces etc
}
If the above is correct then you can overload your Assignment operator to pass the values you wish to pass.
This might be useful to you as well.
C# - Multiple generic types in one list
in this loop parent == Children[i] and Children is a getter for children
Do you really mean to be adding the same node to children and parent, which would make the same node a sibling of parent in addition to a child? I'm not clear on what you're really trying to do but this seems wrong:
if ((parent.Children == null) || (parent.Children[1] == null))
{
children.Add(node);
parent.Add(node);
..
}
edit
From the supporting code you posted the problem could be related to how you create objects:
/* outside the loop */
Gene funcGene = new Gene();
Gene termGene = new Gene();
...
/* inside the loop*/
funcGene.GenerateValue(GeneType.Function);
GeneNode<Gene> geneNode = new GeneNode<Gene>(funcGene);
sChromosome += " " + geneNode.Value;
chromosone.addFull(geneNode);
Seems like you are create a new GeneNode multiple times using a one of two instances of Gene in its constructor. Assuming that your GeneNode is saving that as a property value, each GeneNode is going to reference the same instance of Gene (well, one of two, either funcGene or termGene). I'm guessing this is what you mean when you say new item with the same type as previous items in the ArrayList this new item overwrites the previous items individual properties. Any changes to a Gene property assigned from the constructor in any node of the same type will refer to the same Gene. Even though you are creating new GeneNodes they are constructed from the same Gene.
So assuming that GeneNode.Value references the Gene that it was constructed with, there can only be two different values returned (corresponding to the the current value of one of the two Gene instances) by any node at any given point in time.
Probably, you want to move the code to create a new Gene inside your loop.

Reverse a single chained List

I hope I am using the right terminology.
I have made a single-chained list.
class MyStack
{
public Node Initial { get; set; }
public MyStack()
{
Initial = null;
}
public void Push(int data)
{
var node = new Node { Data = data, Next = Initial };
Initial = node;
}
public int Pop()
{
int res = Initial.Data;
Initial = Initial.Next;
return res;
}
public int Sum()
{
int sum = 0;
Node currentNode = Initial;
while (currentNode != null)
{
sum += currentNode.Data;
currentNode = currentNode.Next;
}
return sum;
}
public int Count()
{
int count = 0;
Node currentNode = Initial;
while (currentNode != null)
{
count++;
currentNode = currentNode.Next;
}
return count;
}
public void PrintAll()
{
Node currentNode = Initial;
while(currentNode != null)
{
Console.WriteLine("tmp.Data = " + currentNode.Data);
currentNode = currentNode.Next;
}
}
}
public class Node
{
public int Data;
public Node Next;
}
Meaning you can do something like this:
var s = new MyStack();
s.Push(5);
s.Push(3);
s.Push(7);
s.PrintAll();
Console.WriteLine("Sum: " + s.Sum());
Console.WriteLine("Count: " + s.Count());
Now, I want to try and make a Reverse method. This seems to be working:
public void Reverse()
{
Node predesesor, location;
location = Initial;
predesesor = null;
while(Initial != null)
{
Initial = Initial.Next;
location.Next = predesesor;
predesesor = location;
location = Initial;
}
Initial = predesesor;
}
I am hardly able to see how it works, and it will be tough to maintain.
It seems more like a hack than anything else.
Can you offer any assistance?
It doesn't seem like a hack to me and I don't see what's there to maintain (it is either correct or not, what else would you do with it?). If you want to figure out how it works, "execute" each step on paper. Draw a list (e.g 1 -> 3 -> 5 -> 7 -> 9 -> NULL), mark out where all Nodes point at any time and start "single-stepping".
I couldn't think of a cleaner way to reverse a singly linked list. You need a reference to the next node (Initial at the beginning of the loop), before you can reverse the link between current node and previous node. You just won't be able to move on in the original list otherwise.
What you could do is fix the spelling of the variables and perhaps not use Initial in the loop itself (use a third variable, so the role of each variable is clearer) and only set Initial to the first Node in the reversed list at the end.
So, all in all:
public void Reverse() {
Node current = Initial, previous = null;
while (current) {
Node next = current.Next;
current.Next = previous;
previous = current;
current = next;
}
Initial = previous;
}
One solution would be to turn it into a doubly-linked list, and then work backwards using the previous node property:
public class Node
{
public int Data;
public Node Next;
public Node Previous;
}
There is already a doubly-linked list in the framework if you want to save yourself some effort.
you can do it recursivly:
a->b->c->d
a->null
b->null
c->null
c<-d
b<-c
a<-b
a<-b<-c<-d
public void Reverse()
{
Reverse(Initial);
}
private void Reverse(Node node)
{
if(node != null && node.Next != null)
{
//go deeper
Reverse(node.Next);
//swap
node.Next.Next = node
node.Next = null;
}
}
Instead of reinventing the wheel you should check, if there is already something you can use something from .Net Framework.
For example i would take here the LinkedList with the LinkedListNode. In other cases you could probably take the Queue or a Stack.
If you call it "nreverse" or "reverse in place" then any developer worth tuppence would recognise it as a classic algorithm rather than a hack.
It shouldn't require much maintenance, except maybe renaming any incorrectly spelled variables.
The following code might be a bit more intuitive:
public void Reverse()
{
MyStack reverse = new MyStack();
while (Initial != null)
{
reverse.Push(this.Pop());
}
Initial = reverse.Initial;
}
(Reverse is a member method of the MyStack class).
Of course, it does require twice the space compared with the original code.
stack s1
s1.push_front(...)
...
s1.push_front(...)
////////////////////////////////////////////////////////
void reverse(stack& to,stack_or_list& s )
while(!s.empty()){
to.push_front(s.pop_front());
}
}
now a series of to.pop_fronts gets you what you want
stack_or_list needs: pop_front empty
to needs: push_front,pop_front

Categories