Singly linked code explanation - c#

I came across this singly linked list implementation in a book. However, I don't understand some statements. My questions against each statement are listed against each statement.
1 class Node {
2 Node next = null; //Is this a constructor?
3 int data;
4 public Node(int d) { data = d; }
5 void appendToTail(int d) {
6 Node end = new Node(d);
7 Node n = this;//Why is "this" keyword used here? What does this do?
8 while (n.next != null) { n = n.next; }//Where does "next" member come from?
9 n.next = end;
10 }
11 }

2 Node next = null; //Is this a constructor? NO it is not.
4 public Node(int d) { data = d; } //This is constructor
7 Node n = this; //The this keyword refers to the current instance of the class
8 while (n.next != null) { n = n.next; } //Learn Linked list

Related

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

swapping nodes in doubly linked list

Trying to swap the second and third nodes from a doubly linked list in c# with the following method:-
public static void swapNodes(List dblLinkList)
{
Node tempnodeTwo = dblLinkList.firstNode.next; //node two in list
Node tempnodeThree = dblLinkList.firstNode.next.next; //node three in list
Node tempnodeFive = tempnodeTwo.previous;
Node tempnodeSix = tempnodeThree.next;
tempnodeThree.previous = tempnodeFive;
tempnodeThree.next = tempnodeThree;
tempnodeTwo.previous = tempnodeTwo;
tempnodeTwo.next = tempnodeSix;
}
The following shows the output: The first is the original list and the second is the result of the method.
N:19:16 19:16:9 16:9:15 9:15:15 15:15:N
N:19:16 16:16:15 9:15:15 15:15:N
Where am I going wrong?? I have already studied previous questions about this topic which gave me the idea for the code but now stuck!
It seems that you assume tempnodeThree is the third and tempnodeTwo is the second node
of the linked list regardless of the changes you make but this is not the case.
After the initializations what you get is:
tempnodeFive <--> tempnodeTwo <--> tempnodeThree <--> tempnodeSix
And you need is:
tempnodeFive <--> tempnodeThree <--> tempnodeTwo <--> tempnodeSix
So what you have to change from left to right are:
tempNodeFive.next, tempNodeTwo.previous, tempNodeTwo.next, tempNodeThree.previous, tempNodeThree.next, tempNodeSix.previous
Let's go over them following the 2nd linked list representation:
tempNodeFive.next = tempNodeThree;
tempNodeTwo.previous = tempnodeThree;
tempNodeTwo.next = tempnodeSix;
tempNodeThree.previous = tempnodeFive;
tempNodeThree.next = tempnodeTwo;
tempNodeSix.previous = tempnodeTwo;
These six lines are what you need.
PS: You can reconsider variable names for a readable and maintainable code, esp. tempNodeFive and tempnodeSix because five and six does not make any sense as an index and it arises confusion while reading the code.
well here in these lines
tempnodeThree.next = tempnodeThree;
tempnodeTwo.previous = tempnodeTwo;
you are setting the next of a node to itself and the previous of another to itself.
don't you mean
tempnodeThree.next = tempnodeTwo;
tempnodeTwo.previous = tempnodeThree;
I think you would have an easier time if you used better names.
I also would not implement this function like this -- I'd make the function suit it's name like this:
public static void swapNodes(Node a, Node b)
{
if (a == null) return;
if (b == null) return;
Node afterA = a.next;
Node beforeA = a.previous;
a.previous = b.previous;
if (b.previous != null) b.previous.next = a;
a.next = b.next;
if (b.next != null) b.next.previous = a;
b.next = afterA;
if (afterA != null) afterA.previous = b;
b.previous = beforeA;
if (beforeA != null) beforeA.next = b;
}
// call it like this
swapNodes(dblLinkList.firstNode.next, dblLinkList.firstNode.next.next);
Are you sure it's c#? Looks like java. C# has LinkedListNode<T> class, not Node. And LinkedListNode<T> has Next and Previous properties. With capitals. And they are read only.
Any way c# implementation looks like this:
using System;
using System.Collections.Generic;
namespace LinkedListSwap
{
class Program
{
static void Main(string[] args)
{
var list = new LinkedList<string>(new[] { "1st", "2nd", "3rd", "4th", "5th", "6th", "7th" });
Console.WriteLine(list.ToDisplayString());
list.Swap(2, 3);
Console.WriteLine(list.ToDisplayString());
}
}
static class LinkedListExtensions
{
public static void Swap<T>(this LinkedList<T> list, int firstIndex, int secondIndex)
{
if (firstIndex < 1 || firstIndex > list.Count)
throw new IndexOutOfRangeException($"Index out of range: {nameof(firstIndex)}");
if (secondIndex < 1 || secondIndex > list.Count)
throw new IndexOutOfRangeException($"Index out of range: {nameof(secondIndex)}");
if (firstIndex == secondIndex)
return;
if (firstIndex > secondIndex)
(firstIndex, secondIndex) = (secondIndex, firstIndex);
int i = 0;
var leftNode = list.First;
while (++i < firstIndex)
leftNode = leftNode.Next;
var rightNode = leftNode.Next;
while (++i < secondIndex)
rightNode = rightNode.Next;
list.Replace(leftNode, rightNode);
list.Replace(rightNode, leftNode);
}
public static void Replace<T>(this LinkedList<T> list, LinkedListNode<T> oldNode, LinkedListNode<T> newNode)
{
list.AddAfter(oldNode, new LinkedListNode<T>(newNode.Value));
list.Remove(oldNode);
}
public static string ToDisplayString<T>(this LinkedList<T> list) => string.Join(" ", list);
}
}
Output is:
1st 2nd 3rd 4th 5th 6th 7th
1st 3rd 2nd 4th 5th 6th 7th

Undestanding Basic LinkedList

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

find subtree from binary tree

See below binary tree.
And see implementation of this algo here: http://msdn.microsoft.com/en-us/library/ms379572(v=vs.80).aspx
1 level 0
2 3 level 1
4 5 6 7 level 2
8 9 10 11 12 13 14 15 level 3
My question is: How do I discover subtree from this tree based on the level? Lets say I want to discover two leveled subtree from 15 numbered node. Then result should be
3
6 7
12 13 14 15
If I search 3 leveled tree then it should be returned me above described full tree from 1 to 15.
Give me suggest for any code or algorithm or function which should be resolve this problem?
Assuming a Node class defined as:
public class Node
{
public Node Left { get; set; }
public Node Right { get; set; }
public int Value { get; set; }
public Node(int value)
{
Value = value;
}
}
You can add the following two methods to this class to achieve what you're trying to do:
public Node GetSubtree(int value, int depth)
{
int foundDepth;
return GetSubtreeHelper(value, depth, out foundDepth);
}
private Node GetSubtreeHelper(int value, int depth, out int foundDepth)
{
if (Value == value)
{
foundDepth = 0;
return depth == foundDepth ? this : null;
}
if (Left != null)
{
var node = Left.GetSubtreeHelper(value, depth, out foundDepth);
if (foundDepth != -1)
{
return ++foundDepth == depth ? this : node;
}
}
if (Right != null)
{
var node = Right.GetSubtreeHelper(value, depth, out foundDepth);
if (foundDepth != -1)
{
return ++foundDepth == depth ? this : node;
}
}
foundDepth = -1;
return null;
}
Testing this using the tree in your question:
GetSubtree(15, 0) = Node 15
GetSubtree(15, 1) = Node 7
GetSubtree(15, 2) = Node 3
GetSubtree(15, 3) = Node 1
GetSubtree(15, 4) = null

Creating custom LinkedList

I am working on creating my own LinkedList. But I can't seem to solve this error. Can anyone help me!
The problem is that I want to insert an object after a particular element. I have created Find method to search for that particular item and return its reference, but I can't seem to solve it.
CustomLinkedList c = new CustomLinkedList();
c.Add(31);
c.Add(45);
c.Add(23);
c.Add(36);
c.PrintList();
Console.WriteLine("\n" + " Process of adding item at a spectifed location");
c.Addafter(66,23);
c.PrintList();
class Node
{
public object Element;
public Node Link;
public Node()
{
Element = null;
Link = null;
}
public Node(object TheElement)
{
Element = TheElement;
Link = null;
}
class CustomLinkedList
{
protected Node header;
protected Node last;
public CustomLinkedList()
{
//header = new Node("header");
}
private Node Find(object Item)
{
Node Current = new Node();
Current = header;
while (Current.Element != Item && Current.Link !=null)
{
Current = Current.Link;
}
return Current;
}
public void PrintList()
{
Node n = new Node();
n = header;
while (n != null)
{
Console.WriteLine(n.Element);
n = n.Link;
}
}
public void Add(object a)
{
Node n = new Node();
n.Element = a;
n.Link = null;
if (last == null)
{
header = n;
last = n;
}
else
{
last.Link = n;
last = n;
}
}
public void Addafter(object newitem, object After)
{
Node current = new Node();
Node newNode = new Node(newitem);
current = Find(After);
newNode.Link = current.Link;
current.Link = newNode;
}
}
The reason why it doesn't work is on this line:
while (Current.Element != Item && Current.Link !=null)
The == and != operators for the object type check for reference equality. If you're using your list with a value type (int for instance), the values will be boxed to distinct objects, and the != operator will always return true (see this article for details about boxing).
Consider this:
object x = 42;
object y = 42;
Console.WriteLine(x == y); // prints False
Console.WriteLine(x.Equals(y)); // prints True
Your current code is working fine with reference types:
var list = new CustomLinkedList();
list.Add("hello");
list.Add("!");
list.Addafter("world", "hello");
list.PrintList();
Output:
hello
world
!
But for value types it never finds the "after" value, so it appends the new item to the end of the list:
var list = new CustomLinkedList();
list.Add(1);
list.Add(3);
list.Addafter(2, 1);
list.PrintList();
Output:
1
3
2
So you need to replace the == operator with a call to Equals:
while (!object.Equals(Current.Element, Item) && Current.Link !=null)
I don't know what you're using for testing but value types won't work the way you think it should because the box values are being compared.
For example this will always return 3 (last element in list)
CustomLinkedList cList= new CustomLinkedList();
cList.Add(1);
cList.Add(2);
cList.Add(3);
Console.WriteLine(cList.Find(2).Element);
but this will work (output 2)
CustomLinkedList cll = new CustomLinkedList();
object a = 1;
object b = 2;
object c = 3;
cll.Add(a);
cll.Add(b);
cll.Add(c);
Console.WriteLine(cll.Find(b).Element);
The same goes for reference types that don't implement the != operators. So strings will work but little else will
Your code has 2 problems
The Find() function is returning the Tail element when the Item is not in the List.
Comparing n.Element and Item is tricky when they are of type object. Make your classes generic to solve that.
...
class CustomLinkedList<T> where T : IEquatable
{
....
private Node Find(object Item)
{
Node Current = header; // null for empty list
//while (Current.Element != Item && Current.Link !=null)
while(Current != null)
{
if (Current.Equals(Item) ) // can't always use ==
break;
Current = Current.Link;
}
return Current;
}
}

Categories