Working on MergeSort in Java:
public void mergeSort(int[] A)
{
if (A.length > 1)
{
int q = A.length/2;
int[] leftArray = Arrays.copyOfRange(A, 0, q);
int[] rightArray = Arrays.copyOfRange(A,q,A.length);
mergeSort(leftArray);
mergeSort(rightArray);
merge(A,leftArray,rightArray);
}
}
The recursion in the code above works well in Java.
So for curiosity I want to convert function Arrays.copyOfRange from java to c#. Array.copy in C# takes five arguments. Do you know any simpler function in c# do get certain elements of the array starting at position x to y (like java).
In c# I coded the above method like this:
public void mergeSort(int[] A)
{
if (A.Length > 1)
{
int q = A.Length / 2;
int[] leftArray = new int[q];
int[] rightArray = new int[A.Length];
for (int i = 0; i < q; i++)
{
leftArray[i] = A[i];
Console.WriteLine(leftArray[i]);
}
for (int i = q; i < A.Length; i++)
{
rightArray[i] = A[i];
Console.WriteLine(rightArray[i]);
}
Console.ReadKey();
mergeSort(leftArray);
mergeSort(rightArray);
merge(A, leftArray, rightArray);
}
}
As you can see I have replaced Arrays.copyOfRange functions in Java with two loops in c# and this works in c# without recursion. However calling mergeSort(leftArray) and mergeSort(rightArray) it prints this in c#:
Process is terminated due to StackOverflowException!!
Any better idea on how to get certain elements in c#?
The problem is the ported array copy is not doing the same thing.
Given an input of [a,b,c,d,e,f]
the Java code is creating two arrays, [a,b,c]
and [d,e,f]
while the C# port is creating two arrays, [a,b,c]
and [0,0,0,d,e,f]
. Notably,
new int[A.Length]
). This is what causes the StackOverflowException as the termination case is never reached, and;q
index, which is the half-way index.Consider this replacement method using Array.Copy
- a method with the same signature can be used as a drop in replacement in ported code, as long as what's inside the method has the same effect as the original.
int[] copyOfRange (int[] src, int start, int end) {
int len = end - start;
int[] dest = new int[len];
Array.Copy(src, start, dest, 0, len);
return dest;
}
Or, a version that does it with a loop but without the issue in the original port. Another reason to use discreet functions - it makes the task easy to see and reason about. Being able to also eliminate duplicate code doesn't hurt.
int[] copyOfRange (int[] src, int start, int end) {
int len = end - start;
int[] dest = new int[len];
// note i is always from 0
for (int i = 0; i < len; i++)
{
dest[i] = src[start + i]; // so 0..n = 0+x..n+x
}
return dest;
}
If you're lazy like me, the code could also be trivially written using LINQ.
int[] leftArray = A.Take(q).ToArray();
int[] rightArray = A.Skip(q).ToArray();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With