Как распечатать пошаговый процесс в MergeSort
У меня проблемы с печатью MergeSort. Мне нужна помощь в распечатке каждого пошагового процесса, так как он сортирует ArrayList.
Следующий пример взят из InsertionSort, так как я печатал его каждый раз, когда он менял два элемента в ArrayList:
11 79 60 45 START
11 79 60 45
11 60 79 45
11 45 60 79 FINISH
Есть ли в любом случае сделать это для MergeSort при отображении всего массива от начала до конца (как выше?)
Код:
import java.util.ArrayList;
public class Merge
{
public static void main (String [] args)
{
Merge run = new Merge();
run.test();
}
public void test ( )
{
ArrayList<Integer> numbers = new ArrayList<Integer>();
for (int i = 0; i < 16; i++)
{
numbers.add(new Integer(1 + (int)(Math.random() * 100)));
}
printArray(numbers);
mergeSort(numbers);
printArray(numbers);
}
public void printArray (ArrayList<Integer> array)
{
System.out.println("\n\n");
for (int i = 0; i < array.size(); i++)
{
System.out.printf("%-5d",array.get(i).intValue());
}
System.out.println("\n\n");
}
public void mergeSort (ArrayList<Integer> array)
{
int length = array.size();
if (length < 2)
{
return; // the array is already sorted in this case
}
// divide
ArrayList<Integer> array1 = new ArrayList<Integer>();
ArrayList<Integer> array2 = new ArrayList<Integer>();
int i = 0;
while (i < length/2)
{
array1.add(array.remove(0)); // move the first n/2 elements to array1
i++;
}
while (!array.isEmpty())
{
array2.add(array.remove(0)); // move the rest to array2
}
mergeSort(array1);
mergeSort(array2);
merge(array1,array2,array);
}
public void merge (ArrayList<Integer> array1, ArrayList<Integer> array2, ArrayList<Integer> array)
{
while (!array1.isEmpty() && !array2.isEmpty())
{
if ((array1.get(0).compareTo(array2.get(0)) <= 0))
{
array.add(array1.remove(0));
}
else
{
array.add(array2.remove(0));
}
}
while(!array1.isEmpty()) // move the remaining elements of array1
{
array.add(array1.remove(0));
}
while(!array2.isEmpty()) // move the remaining elements of array2
{
array.add(array2.remove(0));
}
}
}
3 ответа
Если вы передали какое-то смещение mergeSort
, вы можете распечатать вложенный массив с отступом в том месте, где он будет находиться в полном массиве, когда вы делаете перестановки, но так как вы передаете только части массива вниз, вы не сможете отобразить полный массив таким образом. Тем не менее, есть более быстрый способ, который позволит вам.
Вместо того, чтобы создавать новые массивы и передавать их вниз, передайте массив и 2 индекса, начальную и конечную точки. Итак, ты говоришь mergeSort(array, 0, n)
для первого, затем mergeSort(array, 0, n/2)
а также mergeSort(array, n/2, n)
для рекурсивных вызовов. Вы делаете свое расщепление и слияние только в этих пределах. Затем при слиянии вы можете распечатать весь объединенный массив. Это будет показывать шаг при каждом слиянии. На нижнем уровне будет отображаться своп 1-1 (если это произойдет). Это единственный "шаг за шагом", который вы можете увидеть в слиянии.
Вот небольшая программа алгоритма сортировки слиянием. Я скопировал алгоритм с http://en.wikipedia.org/wiki/Merge_sort. Вы можете просто запустить его как JUnittest или запустить метод main.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import junit.framework.TestCase;
/**
* Simple MergeSortTest
*/
public class MergeSortTest extends TestCase {
private static int FIRST_ENTRY = 0;
public static void main(String[] args) {
MergeSortTest mergesorttest = new MergeSortTest();
Integer [] unsortedInt = {1,38, 27, 110, 9, 82, 10, 100, 299, 13};
List<Integer> unsorted = Arrays.asList(unsortedInt);
List<Integer> sorted = mergesorttest.mergeSort(unsorted);
System.out.println(sorted.toString());
}
public void testMergeSort() {
Integer [] unsortedInt = {1,38, 27, 110, 9, 82, 10, 100, 299, 13};
List<Integer> unsorted = Arrays.asList(unsortedInt);
List<Integer> sorted = mergeSort(unsorted);
assertEquals("[1, 9, 10, 13, 27, 38, 82, 100, 110, 299]", sorted.toString());
}
private List<Integer> mergeSort(List<Integer> list) {
List<Integer> result;
List<Integer> left = new ArrayList<Integer>();
List<Integer> right = new ArrayList<Integer>();;
int middle;
int counter;
if (list.size() <= 1) {
return list;
}
middle = list.size() / 2;
for (counter = 0; counter < middle; counter++) {
left.add(list.get(counter));
}
for (counter = middle; counter < list.size(); counter++) {
right.add(list.get(counter));
}
left = mergeSort(left);
right = mergeSort(right);
result = merge(left, right);
System.out.println(result);
return result;
}
private List<Integer> merge(List<Integer> left, List<Integer> right) {
List<Integer> result = new ArrayList<Integer>();
while (!left.isEmpty() || !right.isEmpty()) {
if (!left.isEmpty() && !right.isEmpty()) {
if (left.get(FIRST_ENTRY) <= right.get(FIRST_ENTRY)) {
handle(left, result);
} else {
handle(right, result);
}
} else if (!left.isEmpty()) {
handle(left, result);
} else if (!right.isEmpty()) {
handle(right, result);
}
}
return result;
}
private void handle(List<Integer> list, List<Integer> result) {
if (!list.isEmpty()) {
result.add(list.get(FIRST_ENTRY));
list.remove(FIRST_ENTRY);
}
}
}
Из-за того, что вы не видите ваш код, трудно точно знать, но я взял реализацию Mergesort отсюда: http://www.vogella.de/articles/JavaAlgorithmsMergesort/article.html.
Я обновил его, чтобы распечатать, как вы хотите.
public class Mergesort
{
private int[] numbers;
private int[] helper;
private int number;
public void sort(int[] values)
{
this.numbers = values;
number = values.length;
this.helper = new int[number];
System.out.println("START");
mergesort(0, number - 1);
System.out.println("END");
}
private void mergesort(int low, int high)
{
// Check if low is smaller then high, if not then the array is sorted
if (low < high)
{
// Get the index of the element which is in the middle
int middle = (low + high) / 2;
// Sort the left side of the array
mergesort(low, middle);
// Sort the right side of the array
mergesort(middle + 1, high);
// Combine them both
merge(low, middle, high);
}
}
private void merge(int low, int middle, int high)
{
// Copy both parts into the helper array
for (int i = low; i <= high; i++)
{
helper[i] = numbers[i];
}
int i = low;
int j = middle + 1;
int k = low;
// Copy the smallest values from either the left or the right side back
// to the original array
while (i <= middle && j <= high)
{
if (helper[i] <= helper[j])
{
numbers[k] = helper[i];
i++;
}
else
{
numbers[k] = helper[j];
j++;
}
k++;
}
// Copy the rest of the left side of the array into the target array
while (i <= middle)
{
numbers[k] = helper[i];
k++;
i++;
}
}
private void printArray()
{
for(int x : numbers)
System.out.print(x + " ");
System.out.println(" ");
}
}
Если вы не хотите печатать на консоль, вы можете построить вывод в строку вывода и вернуть его, когда все будет готово.