C# get value from a LinkedList - c#

I'm currently working in a program which contains a class named LinkedList. It uses nodes to create the functions Add at beginning, Insert At Position, Get Info at position and Eliminate at position. I'm having trouble with the Get function because it's not getting the correct value from the list and I don't know exaclty why.
The definition for Node in the program is:
public class Node<T>
{
public T value;
public Node<T> next;
}
The code for the Get function is:
public T Get(int index)
{
if (start == null)
{
throw new Exception("Nothing to show");
}
if (index == 0)
{
return start.value;
}
Node<T> previous = start;
for (int i = 0; i < index; i++)
{
previous = previous.next;
}
return previous.value;
}
Also, I have these tests where my code is failing when the Get is used. The lists are created when the class LinkedList is used an then, it uses his attributes to invoke the Add, Get, AddAt and Eliminate functions in the tests.
[Test]
public void AddMultipleThenGetAll ()
{
LinkedList<int> linkedList = new LinkedList<int>();
linkedList.Add(42);
linkedList.Add(43);
linkedList.Add(44);
int[] results = new int[] { 42, 43, 44 };
for (int i = 0; i < results.Length; i++)
{
if (linkedList.Get(i) != results[i])
Assert.Fail();
}
Assert.Pass();
}
[Test]
public void AddMultipleAndRemoveInTheMiddle()
{
LinkedList<int> linkedList = new LinkedList<int>();
linkedList.Add(42);
linkedList.Add(43);
linkedList.Add(44);
linkedList.Remove(1);
Console.WriteLine(linkedList);
Assert.AreEqual(44, linkedList.Get(1));
}
The rest of functions are working properly.

Your for loop in your get method has a bug. You are looping all the way to your desired index then setting previous to the next item, which doesn't exist or it isn't the index / item you want. Try this instead.
Node<T> previous = start;
for (int i = 0; i < index - 1; i++)
{
previous = previous.next;
}
return previous.value;

Related

c# find max value recursive (fastest)

I'm out of ideas on this one. Tried originally myself and then copied from SO and google, which worked on all cases except one, however still didn't find a recursive algorithm that is fast enough for that particular test case in my assignment :/
In any case, why this:
public static int FindMaximum(int[] array)
{
if (array is null)
{
throw new ArgumentNullException(nameof(array));
}
if (array.Length == 0)
{
throw new ArgumentException(null);
}
return FindMaxRec(array, array.Length);
}
public static int FindMaxRec(int[] arr, int n)
{
if (n == 1)
{
return arr[0];
}
return Math.Max(arr[n - 1], FindMaxRec(arr, n - 1));
}
doesn't work with this TestCase?:
[Test]
[Order(0)]
[Timeout(5_000)]
public void FindMaximum_TestForLargeArray()
{
int expected = this.max;
int actual = FindMaximum(this.array);
Assert.AreEqual(expected, actual);
}
EDIT 1:
This works fine though, but I need recursive:
public static int FindMaximum(int[] array)
{
if (array is null)
{
throw new ArgumentNullException(nameof(array));
}
if (array.Length == 0)
{
throw new ArgumentException(null);
}
int maxValue = int.MinValue;
for (int i = 0; i < array.Length; i++)
{
if (array[i] > maxValue)
{
maxValue = array[i];
}
}
return maxValue;
}
You can try splitting array in two:
public static int FindMaximum(int[] array) {
if (null == array)
throw new ArgumentNullException(nameof(array));
if (array.Length <= 0)
throw new ArgumentException("Empty array is not allowed.", nameof(array));
return FindMaxRec(array, 0, array.Length - 1);
}
private static int FindMaxRec(int[] array, int from, int to) {
if (to < from)
throw new ArgumentOutOfRangeException(nameof(to));
if (to <= from + 1)
return Math.Max(array[from], array[to]);
return Math.Max(FindMaxRec(array, from, (from + to) / 2),
FindMaxRec(array, (from + to) / 2 + 1, to));
}
Demo:
Random random = new Random(123);
int[] data = Enumerable
.Range(0, 10_000_000)
.Select(_ => random.Next(1_000_000_000))
.ToArray();
Stopwatch sw = new Stopwatch();
sw.Start();
int max = FindMaximum(data);
sw.Stop();
Console.WriteLine($"max = {max}");
Console.WriteLine($"time = {sw.ElapsedMilliseconds}");
Outcome:
max = 999999635
time = 100
An easy way to turn a simple linear algorithm into a recursive one is to make use of the enumerator of the array.
public static int FindMax(int[] values)
{
using var enumerator = values.GetEnumerator();
return FindMaxRecursively(enumerator, int.MinValue);
}
private static T FindMaxRecursively<T>(IEnumerator<T> enumerator, T currentMax) where T : IComparable
{
if (!enumerator.MoveNext()) return currentMax;
var currentValue = enumerator.Current;
if (currentValue.CompareTo(currentMax) > 0) currentMax = currentValue;
return FindMaxRecursively(enumerator, currentMax);
}
This passes your test case and uses recursion.
Edit: Here is a more beginner friendly version of the above, with comments to explain what it is doing:
public static int FindMax(IEnumerable<int> values)
{
using var enumerator = values.GetEnumerator();//the using statement disposes the enumerator when we are done
//disposing the enumerator is important because we want to reset the index back to zero for the next time someone enumerates the array
return FindMaxRecursively(enumerator, int.MinValue);
}
private static int FindMaxRecursively(IEnumerator<int> enumerator, int currentMax)
{
if (!enumerator.MoveNext()) //move to the next item in the array. If there are no more items in the array MoveNext() returns false
return currentMax; //if there are no more items in the array return the current maximum value
var currentValue = enumerator.Current;//this is the value in the array at the current index
if (currentValue > currentMax) currentMax = currentValue;//if it's larger than the current maximum update the maximum
return FindMaxRecursively(enumerator, currentMax);//continue on to the next value, making sure to pass the current maximum
}
Something that might help understand this is that the IEnumerator is what enables foreach loops. Under the hood, foreach loops are just repeatedly calling MoveNext on an item that has an IEnumerator. Here is some more info on that topic.
public static int findMax(int[] a, int index) {
if (index > 0) {
return Math.max(a[index], findMax(a, index-1))
} else {
return a[0];
}
}

C# Radix Sort implementation in LinkedList

i have a task to make a radix sort algorithm for a linkedlist class, i have an object "Info", which has int Year and double Price, i need to sort linked list by Year using radix sorting.
class Info
{
public int Year { get; set; }
public double Price { get; set; }
public Info() { }
public Info(int y, double p)
{
Year = y;
Price = p;
}
}
class Node
{
public Info Data { get; set; }
public Node Next { get; set; }
public Node(Info data, Node adress)
{
Data = data;
Next = adress;
}
}
class LinkedList
{
private Node First;
private Node Last;
private Node Current;
public LinkedList()
{
First = null;
Last = null;
Current = null;
}
}
And i have taken radix sort algorithm for integer from this site. Problem is, i don't know how to modify it to work with my linked class.
static void Sort(int[] arr)
{
int temp = 0;
int i, j;
int[] tmp = new int[arr.Length];
for (int shift = 31; shift > -1; --shift)
{
j = 0;
for (i = 0; i < arr.Length; ++i)
{
bool move = (arr[i] << shift) >= 0;
if (shift == 0 ? !move : move)
arr[i - j] = arr[i];
else
tmp[j++] = arr[i];
}
Array.Copy(tmp, 0, arr, arr.Length - j, j);
}
}
How to make it work with my linked class ?
Based on that code, arr and tmp would need to be linked lists. One issue with this approach is that moving a node requires keeping track of the previous nodes in order to move a node. A dummy head node could be used to provide a node previous to the first data node, or special case handing when moving a node to the start of a list. An alternative would be using two pointers (references) to nodes of temp lists, one where bit == 0, one where bit == 1, and then concatenating the two temp lists into a single list. Note this approach takes 32 passes. If the radix sort were based on a byte instead of a bit, it could be reduced to 4 passes, but would need 256 pointers to nodes for 256 lists.

C#: My Sorting Method/ Printing class does not print the first entry

I have implemented my own selection sort method that seems to be doing it's job for the most part; However, when I am printing files to an excel sheet the printer does not print the first item. I am unsure whether or not the sort method is the source of the problem. My test method for my sort method passes, which is why I am doubting that that is the source. My sort method is shown below. Does it have an error in the scope or order or operations? When I manually move through it on paper everything sorts properly.
public bool sortMaterial()
{
for (int i = 0; i < salesList.Count - 2; i++)
{
Sales curr = salesList[i];
Sales temp;
Sales min = curr;
int swap = 0;
for (int j = i + 1; j < salesList.Count; j++ )
{
temp = salesList[j];
if (String.Compare(temp.material, min.material) == -1)
{
min = temp;
swap = j;
}
}
salesList[i] = min;
salesList[swap] = curr;
}
return true;
}
A neat way to do custom sorting is by implementing the IComparer<T> interface:
public class SalesMaterialComparer : IComparer<Sales> {
public int Compare(Sales x, Sales y) {
return String.Compare(x.material, y.material);
}
}
You can pass your custom comparer to the LINQ OrderBy() method.
IEnumerable<Sales> salesList;
var myComparer = new SalesMaterialComparer();
var sorted = salesList.OrderBy(s => s, myComparer);

Yield return from an indexed iteration via LINQ

Leaving the performance cost of LINQ usage, I would like to know how to convert the following code into a LINQ expression
for (int i = 0; i < someArray.length(); i++)
yield return new SomeEntity(someFunction(i));
Important: I need the use of the incremented index
Update:
Rather than someArray.length(), number should be used:
for (int i = 0; i < number; i++)
yield return new SomeEntity(someFunction(i));
2nd update
I'm still getting the compilation error "not all code paths return value"
My code:
public static IEnumerable function()
{
Enumerable.Range(0,5).Select(i => new Entity());
}
3rd update
Didn't think it's relevant until I found out it's the cause for this error..
public static IEnumerable function()
{
int[] arr = { 1, 2, 3, 4 };
foreach (int i in arr)
{
Enumerable.Range(0,5).Select(i => new Entity());
}
}
If you take out the foreach 1st loop out of the equation, all replies answer to this question, but my issue is n^2.. 2 nested loops...
Any ideas?
Use the overload of Enumerable.Select that has an index into the collection:
someArray.Select((x, i) => new SomeEntity(someFunction(i)));
Edit
As you've modified your example and are not actually using a collection to iterate and index to, use Enumerable.Range:
Enumerable.Range(0, number).Select(i => new SomeEntity(someFunction(i)));
Use Enumerable.Range to generate the numbers:
Enumerable.Range(0,number).Select(i=>new SomeEntity(someFunction(i)));
Here's my LinqPad snippet.
void Main()
{
var e = SomeEntity.GetEntities(new List<int> { 1, 2, 3});
e.Dump();
}
public class SomeEntity
{
public int m_i;
public SomeEntity(int i)
{
m_i = i;
}
public override string ToString()
{
return m_i.ToString();
}
public static int someFunction(int i){ return i+100;}
public static IEnumerable<SomeEntity> GetEntities(IEnumerable<int> someArray)
{
// for (int i = 0; i < someArray.Count();i++)
// yield return new SomeEntity(someFunction(i));
// *** Equivalent linq function ***
return someArray.Select(a => new SomeEntity(someFunction(a)));
}
}

Why is it.current changing his values during debug?

I'm trying to get an element at a specific index with the method :
public T GetElem(int index)
{
var it = outerInstance.iterator();
var i = 0;
while (it.MoveNext() && i < index)
{
i++;
}
return it.Current;
}
I have created my own iterator which is an internal class of the outerInstance,during debug the current element is decreasing at the end it becomes null.
My test it's inside console app and looks like this :
Storage<int?> storage = new DynSLinkedList<int?>();
var ranked = new Ranked<int?>(storage);
if (ranked.IsEmpty())
{
Console.WriteLine("is empty \n");
}
for (var i = 1; i <= 10; i++)
ranked.Add(i);
if (!ranked.IsEmpty())
{
Console.WriteLine("is not empty \n");
}
if (ranked.Size() == 10)
{
Console.WriteLine("Size ok \n");
}
for (var i = 0; i <= 9; i++)
{
var element = ranked.GetElem(i);
if (element == 10 - i)
{
Console.WriteLine("get " + i + " elem ok \n");
}
}
Only for i=0 it gets right.
I have tried to write the equivalent for the java method:
#Override
public T getElem(int index) throws IndexOutOfBoundsException {
RWIterator<T> it=support.iterator();
int i=0;
while (it.hasNext() && i<index){
it.next();
i++;
}
return it.next();
}
Your problem is that you are using a single instance to iterate over in the Ranked.GetElem method. The first time you call ranked.GetElem, passing 0, the iterator will be moved one step (it.MoveNext).
At this point the iterator is already pointing to the second element in your list. The next time you call ranked.GetElem, passing 1, the iterator will be moved two spaced further, ending up returning the third element as opposed to the one you are expecting (the second). So on and so forth.
You need to either change the overall approach you are taking or reset the iterator inside the GetElem method so it always starts from the first element.
Try this (assuming you are implementing the Reset() method correctly):
public T GetElem(int index)
{
var it = outerInstance.iterator();
it.Reset();
var i = 0;
while (it.MoveNext() && i < index)
{
i++;
}
return it.Current;
}

Categories

Resources