singly linked list in c# using extension method - c#

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);
}
}

Related

How to get a certain part of a linked list

I have a project at my university and I stumbled upon a problem I am not able to solve.
About the program: I need to create a list of tasks(they can be private or business tasks). I need a function that returns a list of ONLY private tasks and another function that returns a list of ONLY business tasks.
So I have a class "Task" that contains "next" and "prev" connections. The classes "PrivateTask" and "BusinessTask" inherit this class. I also have a class ToDoList where I actually try to create the list.
class ToDoList
{
Task first = null;
Task last = null;
//adds new tasks and sorts them right away
public void AddSorted(Task newTask)
{
if(first == null)
{
first = newTask;
last = newTask;
}
else
{
if(newTask < first)
{
Prepend(newTask);
}
else if(newTask > last)
{
Append(newTask);
}
else
{
Task loopTask = first;
while(newTask > loopTask)
{
loopTask = loopTask.next;
}
AddBefore(loopTask, newTask);
}
}
}
//adds a new task before another chosen task
private void AddBefore(Task Next, Task newTask)
{
newTask.prev = Next.prev;
newTask.next = Next;
Next.prev.next = newTask;
Next.prev = newTask;
}
//adds at the start of the list
private void Prepend(Task newTask)
{
first.prev = newTask;
newTask.next = first;
first = newTask;
}
//adds at the end of the list
private void Append(Task newTask)
{
last.next = newTask;
newTask.prev = last;
last = newTask;
}
And now I need to return a list of BusinessTasks
//returns a list of business tasks
public ToDoList GetBusinessList()
{
ToDoList busList = new ToDoList();
Task loopTask = first;
while(loopTask != null)
{
if(loopTask is BusinessTask)
{
busList.AddSorted(loopTask);
}
loopTask = loopTask.next;
}
return busList;
}
But when I return this list the whole content of the main list synchronizes with this one and I cannot understand why.
You aren't putting copies of your tasks into your new list, you are putting references into the new list. As a result, you are changing the same objects. So when you push an item from your first list into the second list and as a result next and/or prev gets changed, you are changing both lists.
So you need to copy the item from your original list and put the new item in the second list.
while(loopTask != null)
{
if(loopTask is BusinessTask)
{
var clone = loopTask.Clone();
busList.AddSorted(clone);
}
loopTask = loopTask.next;
}
Now obviously you'll need to implement a Clone method that will copy all the properties except those that relate to the position in the list (prev and next) to a new instance of BusinessTask
Now if you actually want to have the object in both lists to be references to the same object. So that changing a property on one will change the other, then you can get clever by separating out the data part from the list node part. So you could do something like:
public class TaskBase
{
public string SomeProperty { get; set; }
}
public class Node
{
public TaskBase Data { get; private set;}
public Node Next { get; set; }
public Node Prev { get; set; }
public Node(TaskBase data)
{
Data = data;
}
public Node Clone()
{
// Now all the data part is the same object
// so changing Data.SomeProperty in one list will be
// reflected in both. But the Next and Prev properties
// are independent.
return new Node(Data);
}
}
And then your loop might look like this:
while(loopTask != null)
{
if(loopTask.Data is BusinessTask) // assuming BusinessTask derives from BaseTask
{
var clone = loopTask.Clone();
// clone contains the same BusinessTask, but it's position in the new list
// won't mess up the old list.
busList.AddSorted(clone);
}
loopTask = loopTask.next;
}

Print Queue implementation by linked list class C#

I am a student and not an advance developer. I faced an issue regarding to construct a program. I have tried a few things, but still could not solved it. The question came from an exam.
Apologize for this post, because my previous two posts were not accepted well. This time I tried, but got no success still for my posted issue.
Question as follows
a) Write a class named Document to represent a document node in a print queue. It should contain a method name that returns the subject of the document and an abstract method called type that returns the document type. Derive from a document class two concrete classes named word document and pdf document.
b) Another class named Print Queue that is implemented as a linked list of Document objects. Print Queue should have a method named Push for adding a document to the end of the list, a method named pop for removing the first document from the list, and a method named DisplayContents for listing all of the documents in the Print Queue, reporting both the Name and Type of each element Print Queue should not use any standard library classes it should be own implementation of linked list.
Here I have coded it that way:
class PrintQueue
{
private Document head;
private int size;
public int Count
{
get
{
return size;
}
}
public void Push(Object data)
{
Document toAdd = new Document();
toAdd.data = data;
Document current = head;
while (current.Next != null)
{
current = current.Next;
}
current.Next = toAdd;
size++;
}
public bool Pop()
{
Document tempNode = head;
Document lastNode = null;
int count = 0;
if (size > 0)
{
while (tempNode != null)
{
if (count == size - 1)
{
lastNode.Next = tempNode.Next;
return true;
}
count++;
lastNode = tempNode;
tempNode = tempNode.Next;
}
}
return false;
}
}
public abstract class Document
{
public Document Next;
public Object data;
public string Subject { get; set; }
public abstract string type();
}
public class WordDocument : Document
{
public override string type()
{
return "docx";
}
}
public class PdfDocument : Document
{
public override string type()
{
return "pdf";
}
}
This line causes the problem Document toAdd = new Document();
But I still could not find a way for DisplayContents function which will list all of the documents in the Print Queue, reporting both the Name and Type of each element Print Queue.
Could anyone review my code and help me to get it rectified as per the question. Highlight those areas where I have made mistakes.
Thanks
UPDATE
the 2 questions i was trying to solve as follows
Question 1 : Write a class named Document to represent a document node in a print queue. it should contain a method name that returns the subject of the document and an abstract method called type that returns the document type . from document class derive two concrete classes named word document and pdf document.
Question 2 : Another class named Print Queue that is implemented as a linked list of Document objects. Print Queue should have a method named Push for adding a document to the end of the list, a method named pop for removing the first document from the list , and a method named DisplayContents for listing all of the documents in the Print Queue, reporting both the Name and Type of each element Print Queue should not use any standard library classes it should be own implementation of linked list.
here i like to post whatever at last i achieved. so please see the code and question let me know is it correct as per the 2 question pasted here.
see the latest code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PrintQueueDemo
{
class PrintQueue
{
Node head;
Node tail;
/// <summary>
/// add a document to the print queue
/// </summary>
/// <param name="strType">document type</param>
/// <param name="strName">docunent name</param>
public void Push(string strType, string strName)
{
if (head == null)
{
head = new Node(strType, strName);
tail = head;
}
else
{
Node node = new Node(strType, strName);
tail.setNext(node);
tail = node;
}
}
/// <summary>
/// pop a document from the queue
/// </summary>
/// <returns>null if printqueue is empty, else document</returns>
public Node.Document Pop()
{
if (head == null)
return null;
Node.Document doc = new Node.Document(head.document.Type, head.document.Name);
head = head.nextnode;
if (head == null)
tail = null;
return doc;
}
/// <summary>
/// get the current content of the queue
/// </summary>
/// <returns>string with current content (line per entry)</returns>
public string DisplayContents()
{
string content = "";
Node node = head;
if (node == null)
return "PrintQueue is empty";
content = node.document.Name + ": " + node.document.Type;
while (node.nextnode != null)
{
node = node.nextnode;
content += "\r\n" + node.document.Name + ": " + node.document.Type;
}
return content;
}
public class Node
{
public Document document { get; private set; }
public Node nextnode { get; private set; }
public Node(string strType, string strName)
{
document = new Document(strType, strName);
}
public void setNext(Node node)
{
nextnode = node;
}
public class Document
{
public string Type { get; private set; }
public string Name { get; private set; }
public Document(string strType, string strName)
{
Name = strName;
Type = strType;
}
}
}
}
}
PrintQueue pq = new PrintQueue();
pq.Push("cpp", "main.cpp");
pq.Push("c#", "main.cs");
pq.Push("c", "main.c");
pq.Push("h", "myinclude.h");
Console.WriteLine(pq.DisplayContents());
Console.WriteLine("===");
PrintQueue.Node.Document doc;
doc = pq.Pop();
Console.WriteLine("{0}: {1}", doc.Name, doc.Type);
doc = pq.Pop();
Console.WriteLine("{0}: {1}", doc.Name, doc.Type);
doc = pq.Pop();
Console.WriteLine("{0}: {1}", doc.Name, doc.Type);
doc = pq.Pop();
Console.WriteLine("{0}: {1}", doc.Name, doc.Type);
Console.WriteLine("===");
Console.WriteLine(pq.DisplayContents());
Console.WriteLine("===");
pq.Push("xls", "workbook.xls");
Console.WriteLine(pq.DisplayContents());
just tell me the above code will be accepted as per 2 question which i pasted at top. thanks

How to handle parameters right in 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;
}
}

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.

Filling up a TreeView control

I have a N-Ary non sorted in any way tree and each node can have 0-N children. Given the data structure below, how can I fill the tree view assuming you have an array of TermNodes and that array is the first level of the TreeView? I have not been able to come up with a recursive way to do this.
class TermNode
{
public string Name;
public string Definition;
public List<TermNode> Children
}
Here is a bit of code to get you started with the recursion. It's not tested (I can't right now), but you should get the idea:
public static void BuildTreeView(TreeNodeCollection Parent, List<TermNode> TermNodeList)
{
foreach (TermNode n in TermNodeList)
{
TreeNode CurrentNode = Parent.Add(n.Name);
// no need to recurse on empty list
if (n.List.Count > 0) BuildTreeView(CurrentNode.Nodes, n.List);
}
}
// initial call
List<TermNode> AllTermNodes = /* all your nodes at root level */;
BuildTreeView(treeView1.Nodes, AllTermNodes);
Just took out Generics for a spin.. Worked nicely. Worth a look at...
public interface INode<T>
{
List<T> Children { get; }
}
class TermNode:INode<TermNode>
{
public string Name;
public string Definition;
public List<TermNode> Children { get; set; }
public TermNode()
{
this.Children = new List<TermNode>();
}
}
public class TreeBuilder<T> where T : INode<T>
{
public Func<T, TreeNode> obCreateNodeFunc;
public void AddNode(TreeView obTreeView, T obNodeToAdd, TreeNode obParentNodeIfAny)
{
TreeNodeCollection obNodes;
if (obParentNodeIfAny == null)
{
obNodes = obTreeView.Nodes;
}
else
{
obNodes = obParentNodeIfAny.Nodes;
}
int iNewNodeIndex = obNodes.Add(obCreateNodeFunc(obNodeToAdd));
TreeNode obNewNode = obNodes[iNewNodeIndex];
foreach (T child in obNodeToAdd.Children)
{
AddNode(obTreeView, child, obNewNode);
}
}
}
// calling code - Some class
static TreeNode GetTreeNodeFor(TermNode t)
{
return new TreeNode(t.Name); // or any logic that returns corr TreeNode for T
}
void Main()...
{
TermNode[] arrNodesList;
// populate list with nodes
TreeBuilder<TermNode> tb = new TreeBuilder<TermNode>();
tb.obCreateNodeFunc = GetTreeNodeFor;
foreach (TermNode obNode in arrNodesList)
{
tb.AddNode(treeView, obNode, null);
}
}
Thanks All I was getting confused because I did not realize that for a given TreeNode tn, tn.Nodes.Add would return the added TreeNode
Once you know that the solution is straight forward like so
private void /*TreeNode*/ RecursiveAdd(OntologyNode on, TreeNode tn)
{
if (on.Children.Count == 0)
{
return;
}
foreach (OntologyNode child in on.Children)
{
TreeNode tCur = tn.Nodes.Add(child.Name);
tCur.Tag = child;//optional for some selected node events
RecursiveAdd(child, tCur);
}
}
and to start of the recursive call
foreach( OntologyNode on in Nodes )
{
if (on.IsTopLevelNode == true)// internal not pertinent to this code snippet
{
TreeNode tn = tvOntoBrowser.Nodes.Add(on.Name);
tn.Tag = on;
if (on.Children.Count > 0)
{
RecursiveAdd(on, tn);
}
}
}

Categories

Resources