I have been trying to code merge sort, without creating additional arrays for keeping sorted parts, after few hours I can’t find the error, which causes last bit of the array to be sorted in a wrong order. Theres quite a few helper methods, I used for the debugging, I left them in.
public class Sorter2
{
public static void toString(int [] list)
{
for(int i = 0; i < list.length; i++)
{
System.out.print(list[i]);
if(!(i + 1 == list.length))
{
System.out.print(",");
}
}
System.out.println("");
}
public static void toString(int list[], int from, int to)
{
for(int i = from; i <= to; i++)
{
System.out.print(list[i]);
if(i + 1 <= to)
{
System.out.print(",");
}
}
System.out.println("");
}
public static void insertAt(int [] list, int insert_at, int taken_from)
{
int to_insert = list[taken_from];
for(int i = taken_from; i >= insert_at; i--)
{
if(i != insert_at)
{
list[i] = list[i - 1];
}
else
{
list[i] = to_insert;
}
}
}
public static void sortSegments(int [] list ,int segment_one_begin, int segment_one_end, int segment_two_begin, int segment_two_end)
{
toString(list, segment_one_begin, segment_two_end);
int sorted = 0;
for(int i = segment_two_begin; i <= segment_two_end; i++)
{
for(int l = segment_one_begin + sorted; l <= segment_one_end; l++)
{
if(list[i] <= list[l])
{
insertAt(list, l, i);
sorted++;
}
}
}
toString(list, segment_one_begin, segment_two_end);
}
public static void mergeSort(int [] list, int segment_begining, int segment_end)
{
if(segment_end - segment_begining < 1)
{
return;
}
else
{
int midpoint = (segment_end + segment_begining) / 2;
mergeSort(list, segment_begining, midpoint);
mergeSort(list, midpoint + 1, segment_end);
sortSegments(list, segment_begining, midpoint, midpoint + 1, segment_end);
}
}
public static void mergeSort(int [] list)
{
mergeSort(list, 0, list.length - 1);
}
public static boolean isInOrder(int [] toCheck)
{
for(int i = 1; i < toCheck.length; i++)
{
if(toCheck[i] < toCheck[i - 1])
{
return false;
}
}
return true;
}
public static int [] populate(int numOfItems)
{
int [] toReturn = new int[numOfItems];
for(int i = 0; i < toReturn.length; i++)
{
toReturn[i] = (int) (Math.random() * 100 + 1);
}
return toReturn;
}
public static void main(String [] args)
{
int [] nums = populate(20);
mergeSort(nums);
toString(nums);
System.out.println(isInOrder(nums));
}
}
Let’s adjust your code a bit so that the tests would be reproducible, and we could see the whole process:
The output is as follows:
As you can see, the first problem manifests itself in the following lines:
We take two ordered chunks and get an unordered chunk as a result. Put a breakpoint on line
for (int i = segment_two_begin; i <= segment_two_end; i++) {and try to catch the case forSorter2.sortSegments(0,2,3,4):42 <= 47, so we callinsertAtto move 42 before 47segment_two—and believed to be in place!Here’s the error for you: your
sortSegmentsdoes not work as advertised.If you think a minute about that method, you’ll find that you do not actually need nested loops: all you need is to find the necessary elements, step by step. So you’re better off with one cycle from
segment_one_begintosegment_two_end, and a pointer to a current position in the second list: if an element from first list is lower than one from the second, you just skip to the new position. If it’s not, you perform the shift you need—and move a pointer.I’ve made a fix and it works just fine for me—so it seems is was the only error in your implementation. If you’re still stuck, please describe your problem, and I’ll try to help.