Linked List Implementation by Structure In C#() - c#

I am implementing Linked List in C# so I use Two Approaches
First Approach
unsafe public struct Node
{
public int info;
public Node* link;
}
Here Is Add Node Method
public void AddNode( int a)
{
Node temp = new Node();
temp.info = a;
if (Head == null)
{
Head = Current = &temp;
}
else
{
(*Current).link = &temp;
Current = &temp;
}
}
When I run This Code It does not save memory means It create an instance of Node temp = new Node();Structure as long as it is inside AddNode Its memory is save but when I print It outside this method using Head its give me NullRefrenceException
Second Approach
By Using Class And Objects
public class Node
{
public int info;
public Node link;
}
class Linked_list
{
public Node Head;
public Node Current;
public void insert_element_linkedlist( int a)
{
Node temp = new Node();
temp.info = a;
if (Head == null)
{
Head = Current = temp;
}
else
{
Current.link = temp;
Current = temp;
}
}
}
The Second method is working perfectly means Every instance of temp node Node temp = new Node(); is save in memory .
Question :
Why It does not save structure instance ?
Sorry For My Sub Standard English.

The structure instance, being a value type, gets created on the stack, so when AddNode returns it is cleaned up and you are left with pointers to a random place in memory. Simply creating a pointer to a variable is not enough to keep it alive.

Related

Simple List Merge C# (Without Generics)

I have created a simple list class from scratch. This is for a class assignment that I have been working on for about a week - very new to lists. We can not use generics so trying to research my question below has not been fruitful. Although I did get to watch 7 tutorials on youtube by BetterCoder and I found some stuff in my book but nothing with an example of "merging".
I have three classes - my node, my list, and my program. In my list class, I am working on building a Merge() method which eventually will compare the data in the two lists and merge them into an ordered list.
Right now for some reason my Merge method - which is very basic to help me understand what is happening - is not working correctly. It has both lists passed to it, and is adding the data from listTwo to listOne BUT for some reason when it's printing to the console the second Node's Data shows twice :
EX: 1 -> 2 -> 2
instead of printing the head (1), the next (2) and then the next (3) which it should be.
EX: 1 -> 2 -> 3
In the program class I have proven with a write line that (listOne.firstNode.Next.Next.Data) = 3 . Which it should be.
Can someone help me figure out if the nodes in list one aren't pointing to each other correctly or whatever is going on?
My Merge Method must be passed both list objects (listOne and listTwo) and eventually I need to make those passed as references but I haven't figured that out quite yet and will focus on that later I suppose.
namespace LinkedList
{
//This is my Node Class
class Node
{
public object Data { get; set; }
public Node Next { get; set; }
public Node(object dataValue) : this(dataValue, null) { }
public Node(object dataValue, Node nextNode)
{
Data = dataValue;
Next = nextNode;
}
}
//This is my List Class
class List
{
public Node firstNode;
public int count;
public List()
{
firstNode = null;
}
public bool Empty
{
get { return this.count == 0; }
}
public int Count
{
get { return this.count; }
}
public object Add(int index, object o)
{
if (index < 0)
throw new ArgumentOutOfRangeException("Index: " + index);
if (index > count)
index = count;
Node current = this.firstNode;
if (this.Empty || index == 0)
{
this.firstNode = new Node(o, this.firstNode);
}
else
{
for (int i = 0; i < index - 1; i++)
current = current.Next;
current.Next = new Node(o, current.Next);
}
count++;
return o;
}
public object Add(object o)
{
return this.Add(count, o);
}
public object Merge(List a, List b)
{
a.Add(b.firstNode.Data);
return a;
}
public void Print()
{
while (this.count > 0)
{
Console.Write(firstNode.Data + "->");
if(firstNode.Next != null)
firstNode.Data = firstNode.Next.Data;
count--;
}
}
}
//And here is my Program
class Program
{
static void Main(string[] args)
{
List listOne = new List();
List listTwo = new List();
listOne.Add(1);
listOne.Add(2);
listTwo.Add(3);
listTwo.Print();
Console.WriteLine("");
listOne.Merge(listOne, listTwo);
Console.WriteLine("");
listOne.Print();
//This line below shows that the data "3" from listTwo is being added to listOne in the list Merge Method
//Console.WriteLine(listOne.firstNode.Next.Next.Data);
Console.ReadKey();
}
}
}
Actual problem in your print method
public void Print()
{
Node node = firstNode;
for (int i = 0; i < this.count; i++)
{
Console.Write(node.Data + "->");
if (node.Next != null)
node = node.Next;
}
}
Alex Sikilinda , you are right the merge method is incomplete.
public object Merge(List a, List b)
{
Node bNode = b.firstNode;
while (bNode != null)
{
a.Add(bNode.Data);
bNode = bNode.Next;
}
return a;
}
I would write it this way:
public void Merge(List b)
{
Node lastNode = GetLastNode();
if (lastNode != null)
{
lastNode.Next = b.firstNode;
}
else
{
this.firstNode = b.firstNode;
}
}
// this method is used to find the last node in current list
private Node GetLastNode()
{
if (this.firstNode == null)
{
return null;
}
Node current = this.firstNode;
while (current.Next != null)
{
current = current.Next;
}
return current;
}
First of all, I changed signature of Merge from public object Merge(List a, List b) to public void Merge(List b). Now we can use it like this:
listOne.Merge(listTwo);
This will link listOne's last element with the first element of listTwo and thus they are merged.
Now we need to change Print method since current version modifies the list, which shouldn't happen:
public void Print()
{
Node currentNode = this.firstNode;
while(currentNode != null)
{
Console.Write(currentNode.Data + ' ');
currentNode = currentNode.Next;
}
}
Instead of assigning the data back to first node I assign the
firstNode = firstNode.Next;
Please check the below Print Code
public void Print()
{
while (this.count > 0)
{
Console.Write(firstNode.Data + "->");
if (firstNode.Next != null)
firstNode = firstNode.Next;
count--;
}
}

How do i write a method that removes specific object from linked list?

i didn't succeed to remove specific item from linked list,the method is - public void removeFromList(string itemtoremove, LinkedList List).
How do i write method that removes specific item from linked list?
my code is:
public class Node
{
public Node next; //saves the adress
public Person data; //saves the person
}
public class LinkedList
{
private Node head; //starts from the begging
public void AddFirst(Person data)
{
Node toAdd = new Node();
toAdd.data = data; // in data he saves the object
toAdd.next = head;
head = toAdd;
}
public void removeFromList(string itemtoremove, LinkedList List) //
{
Node current = head;
Node current1 = current.next;
while (current1 != null)
{
if (current1.data.instrument == itemtoremove)
???
}
}
}
Your method already has a problem before you even implement the algorithm. You are skipping the head node. You also don't need to pass the linked list in as a parameter to the instance method.
public void removeFromList(string itemtoremove)
{
Node previousNode = null;
Node current = head;
while (current != null) //starting with current1 would ignore the head node
{
// we found a match
if (current.data.instrument == itemtoremove){
// head node is treated slightly differently
if(current == head){
// set the next node to the new head
head = current.next;
// set to null so GC can clean it up
current = null;
return;
}
else {
//update the previous node's link
previousNode.next = current.next;
current = null;
return;
}
}
// move on to the next
previousNode = current;
current = current.next;
}
}

C# How to pool the objects of a node tree efficiently?

I have a node class that contains only value type properties, and one reference type: it's parent node. When performing tree searches, these nodes are created and destroyed hundreds of thousands of times in a very short time span.
public class Node
{
public Node Parent { get; set; }
public int A { get; set; }
public int B { get; set; }
public int C { get; set; }
public int D { get; set; }
}
The tree search looks something like this:
public static Node GetDepthFirstBest(this ITree tree, Node root)
{
Node bestNode = root;
float bestScore = tree.Evaluate(root);
var stack = new Stack<Node>();
stack.Push(root);
while(stack.Count > 0)
{
var current = stack.Pop();
float score = tree.Evaluate(current);
if (score > bestScore)
{
bestNode = current;
bestScore = score;
}
var children = tree.GetChildren(current);
foreach(var c in children) { stack.Push(c); }
}
return bestNode;
}
Because this is done in a Mono runtime that has a very old GC, I wanted to try and pool the node objects. However, I am at a loss on how to know when a node object is safe to return to the pool, since other nodes that are still in use might reference it as a parent. At the end of the search, the best node is returned and a list of nodes is formed by walking back through its ancestors. I have full control over how the nodes are created inside the tree, if that's useful.
What options could I try and implement?
So, fortunately, if you're doing a Depth-First-Search, which you appear to be, this is a bit easier. Any time you reach a leaf node, there are two possibilities: that leaf node is part of the current deepest tree, or it's not.
If it's not, that means it's safe to return this node to the pool. If it is, that means we can return any nodes in our old tree back to our pool that are not in our own ancestor chain.
Now, if we're not a leafnode, we don't know if we can be freed until after we've finished checking our children. then, once all our children are checked, we find out if any of our children said they were the current best. if so, we keep ourselves
this does mean we're doing quite a bit more checking.
Here's some sudo code:
List bestNodes;
bool evalNode(node, score)
{
if (childCount == 0)
{
if (score > bestScore)
{
bestScore = score;
bestNode = node;
bestNodes.Add(node);
return true;
}
else
{
freeNode(this);
return false;
}
}
else
{
bool inLongest = false;
foreach (child in children)
{
inLongest = evalNode(child, score + 1) || inLongest;
}
if (!inLongest)
{
freeNode(node);
}
else
{
free(bestNodes[score]);
bestNodes[score] = node;
}
return inLongest;
}
}
Try using the ref keyword if your node is a struct, this avoids copying the node every time you pass it through to a function.
Thus:
struct Node
{
object obj;
Node children;
}
public void DoStuffWithNode(ref Node pNode){...Logic...}

Storing an Author class in an AVL tree

I'm creating a software product which is an AVLTree containing the details of Authors. The Author class contains: Name, Year Of Publish and List of Books (using LinkedList<> collection). The Author objects will be stored in the AVLTree with the Name as the key for comparison.
My problem is that I can't seem to store the Author class correctly in the AVLTree.
I appreciate any advice and help.
I create the Author array, and create an AVLTree:
public Author[] author = new Author[i];
public AVLTree<Author> authorAVL = new AVLTree<Author>();
The code for the 'Add Author' button is as follows:
author[i].Name = textBoxAddAuthor.Text;
author[i].YrOfPub = textBoxYrOfPub.Text;
author[i] = new Author(author[i].Name, author[i].YrOfPub);
Array.Sort(author);
authorAVL.InsertItem(artist[i]);
I've implemented CompareTo in the Author class as follows:
public int CompareTo(object obj)
{
if (obj is Author) //compare by name
{
Author other = (Author)obj;
return name.CompareTo(other.name);
}
The InsertItem method in the AVLTree looks like this:
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);
tree.BalanceFactor = (height(tree.Left) - height(tree.Right));
if (tree.BalanceFactor <= -2)
rotateLeft(ref tree);
if (tree.BalanceFactor >= 2)
rotateRight(ref tree);
}
And the node class includes this:
public class Node<T> where T : IComparable
{
private T data;
public Node<T> Left, Right;
private int balanceFactor = 0;
public Node(T item)
{
data = item;
Left = null;
Right = null;
}
public T Data
{
set { data = value; }
get { return data; }
}
public int BalanceFactor
{
set { balanceFactor = value; }
get { return balanceFactor; }
}
}
It seems to me the problem is here:
author[i].Name = textBoxAddAuthor.Text;
author[i].YrOfPub = textBoxYrOfPub.Text;
author[i] = new Author("Name", "yearofpublish");
In particular the order of operations is not right. You are attempting to set properties of author[i] and then you are overwriting that with a new instance of Author.. doesn't make any sense.
It should be:
author[i] = new Author(textBoxAddAuthor.Text, textBoxYrOfPub.Text);
I'm also a bit confused about three other things in your code:
Why do you also have an array holding Authors if you are putting them in the tree in the first place?
Why are you initializing the array of autors like this: public Author[] author = new Author[i];. Where does i come from?
Why are you sorting the array each time you want to insert into the tree? The tree is self-balancing..
And then you are re-using i to initialize/set up the author before inserting into tree.. ?!
To me the following block:
// where does this i come from here?
author[i].Name = textBoxAddAuthor.Text; // this is useless..
author[i].YrOfPub = textBoxYrOfPub.Text; // this is useless..
author[i] = new Author(author[i].Name, author[i].YrOfPub); // overwriting author[i] here
Array.Sort(author); // why are you sorting the array each time you insert?
authorAVL.InsertItem(artist[i]);
Should be re-written as:
Author newAuthor = new Author(textBoxAddAuthor.Text, textBoxYrOfPub.Text);
authorAVL.InsertItem(newAuthor);

Loop detection in LinkedList using C#

In the interview question, "Implement an algorithm which detects for presence of the loop.". For example, the linked list has a loop, like:
0--->1---->2---->3---->4---->5---->6
▲ |
| ▼
11<—-22<—-12<—-9<—-8
Using Floyd's cycle detection, this problem can be solved by using a fast & slow pointer. So should I try comparing
a. Link's node values, i.e.
if (fast.data == slow.data)
break;
where fast and slow are of type Link
class Link
{
int IData {get; set;}
Link Next {get; set;}
}
OR
b. Are they pointing to same reference, i.e. if (fast == slow)
Thanks.
You should only be comparing the nodes themselves. After all, it's reasonable to have a linked list with repeated data in, without it actually having a cycle.
I would call them nodes rather than links too. A link is simply the reference from one node to the next or previous one - in particular, there's no data associated with a link, only with a node.
Hope this helps... It might be naive but it works...
using System;
namespace CSharpTestTemplates
{
class LinkedList
{
Node Head;
public class Node
{
public int value;
public Node NextNode;
public Node(int value)
{
this.value = value;
}
}
public LinkedList(Node head)
{
this.Head = head;
}
public Boolean hasLoop()
{
Node tempNode = Head;
Node tempNode1 = Head.NextNode;
while(tempNode!=null && tempNode1!=null){
if(tempNode.Equals(tempNode1)){
return true;
}
if ((tempNode1.NextNode != null) && (tempNode.NextNode != null))
{
tempNode1 = tempNode1.NextNode.NextNode;
tempNode = tempNode.NextNode;
}
else
{
return false;
}
}
return false;
}
public static void Main()
{
Node head = new Node(1);
LinkedList ll = new LinkedList(head);
Node node2 = new Node(2);
Node node3 = new Node(3);
Node node4 = new Node(4);
Node node5 = new Node(5);
Node node6 = new Node(6);
head.NextNode = node2;
node2.NextNode = node3;
node3.NextNode = node4;
node4.NextNode = node5;
node5.NextNode = node6;
node6.NextNode = null;
Console.WriteLine(ll.hasLoop());
Console.Read();
}
}
}

Categories