2014-02-14 98 views
0

我不明白为什么我的算法使用ArrayList的合并排序程序将无法正常工作...如果家伙和gals可以帮我弄明白,那将是惊人的!打印所需的格式需要按每个数字标签,并且每20个数字放置一个新行。我的程序也仅限于标准的Java程序包。样本输入和输出可以找到here。这里是我的代码:Java合并排序算法错误 - 不排序

import java.io.*; 
import java.util.*; 

public class MergeSort { 
public static void main(String[] args) throws IOException{ 
    Scanner in = new Scanner(System.in); 
    Random r = new Random(); 
    int size, largestInt, holder; 

    System.out.println("How many integers would you like me to create?"); 
    size = in.nextInt(); 
    ArrayList<Integer>list = new ArrayList<Integer>(size); 
    System.out.println("What would the largest integer be?"); 
    largestInt = in.nextInt(); 

    for(int i = 0; i < size; i++){ 
     holder = r.nextInt(largestInt + 1); 
     list.add(holder); 
    } 
    mergeSort(list); 

    for (int j = 0; j < list.size(); j++) { 
     if(j == 19 || j == 39 || j == 59 || j == 79 || j == 99 || j == 119 || j == 139 || j == 159 || j == 179 || j == 199){ 
      System.out.print(list.get(j)); 
      System.out.println(); 
     } 
     else{ 
      System.out.print(list.get(j) + "\t"); 
     } 
    } 
} 

static void mergeSort(ArrayList<Integer> list) { 
    if (list.size() > 1) { 
     int q = list.size()/2; 
     ArrayList<Integer> leftList = new ArrayList<Integer>(); 
     for(int i = 0; i >0 && i <= q; i++){ 
      leftList.add(list.get(i)); 
     } 
     ArrayList<Integer> rightList = new ArrayList<Integer>(); 
     for(int j = 0; j > q && j < list.size(); j++){ 
      rightList.add(list.get(j)); 
     } 

     mergeSort(leftList); 
     mergeSort(rightList); 
     merge(list,leftList,rightList); 
    } 
} 

static void merge(ArrayList<Integer> a, ArrayList<Integer> l, ArrayList<Integer> r) { 
    int totElem = l.size() + r.size(); 
    int i,li,ri; 
    i = li = ri = 0; 
    while (i < totElem) { 
     if ((li < l.size()) && (ri<r.size())) { 
      if (l.get(li) < r.get(ri)) { 
       a.set(i, l.get(li)); 
       i++; 
       li++; 
      } 
      else { 
       a.set(i, r.get(ri)); 
       i++; 
       ri++; 
      } 
     } 
     else { 
      if (li >= l.size()) { 
       while (ri < r.size()) { 
        a.set(i, r.get(ri)); 
        i++; 
        ri++; 
       } 
      } 
      if (ri >= r.size()) { 
       while (li < l.size()) { 
        a.set(i, l.get(li)); 
        li++; 
        i++; 
       } 
      } 
     } 
    } 
} 

在此先感谢!

+0

它以什么方式破碎?向我们展示一些示例输出。 – chm

+0

@ chm052它需要按照从最低值到最高值的顺序打印出来,并且必须使用合并排序算法进行排序(即1,2,3,4,6,19,67,89) –

+1

它当前打印的内容是什么? *给我们一些例子输出*与相应的输入。 – chm

回答

0

你的问题不清楚,但由于你需要实现合并排序算法,我认为这是为你打破的部分。一旦你有一个正确排序的列表,格式化打印应该是相当容易的,通过反复试验。

我认为你的解决方案中的问题非常复杂。 MergeSort是最简单的排序算法之一,但你的代码并不简单。

想想合并排序是如何工作的 - 它本质上是递归的,因为它是一种分而治之的方法。它通过将其分解成小的简单问题来解决一个复杂的大问题,基本上只是将所有这些问题的结果合并 - 您的MergeSort算法只需要包含这些问题。

如果我们写它,你需要做以下步骤:

(1)检查列表仅包含一个元素 - 那么它已经排序

(2)拆分输入同样大小的在继续之前列出并对它们排序(递归步骤)

(3)合并两个排序列表并返回单个排序列表。

我看到你有一个合并部分的复杂方法,并使用分裂部分的基本迭代。 Java List(例如ArrayList的超类)提供.subList(fromIndex, toIndex)将列表拆分为更小的列表。你应该使用这个。对于合并部分:

基于此动画从维基百科

enter image description here

它应该是相当简单的,你应该如何看待合并两个列表:

一是保持两个列表作为列出很容易从中删除对象。由于此时我们知道列表将被排序,因此我们只关心每个列表中的第一个对象(最小的元素)。其次,我们只需要比较每个列表的第一个元素,从其各自的列表中删除最小的两个并将其添加到我们的排序列表中。我们一直这样做直到两个列表都是空的 - 在这一点上,我们已经合并了我们的列表。

在Java中,这表示我们应该使用合并部分的数据结构,它允许我们查看每个列表的第一个元素,并快速删除我们感兴趣的元素。在Java中,此数据结构是LinkedList - ArrayList这两方面都表现得非常糟糕,并没有提供适当的方法来做到这一点。 LinkedList表现为一个队列,并提供了方便检查和删除列表末尾的对象的方法,例如第一个元素。

因此,您应该重新考虑您的实施策略并根据应该如何攻击MergeSort算法来简化代码。如果看起来这里是混淆的,那么在Java中使用MergeSort的示例实现仅使用标准API(在排序方法中不构建)。

希望它有帮助。

import java.util.LinkedList; 
import java.util.Random; 
import java.util.List; 

public class Main { 

    public static void main(String[] args){ 

     Random random = new Random(); 
     LinkedList<Integer> unsorted = new LinkedList<Integer>(); 
     for(int i = 0; i<100; i++){ 
      unsorted.add(random.nextInt(100)); 
     } 

     System.out.println("unsorted: " + unsorted.toString()); 

     List<Integer> sorted = mergeSort(unsorted); 

     System.out.println("sorted: " + sorted.toString()); 
    } 

    //Recursive function for sorting a LinkedList 
    private static LinkedList<Integer> mergeSort(LinkedList<Integer> unsorted){ 

     //If the list only contains 1 object it is sorted 
     if(unsorted.size() == 1){ 
      return unsorted; 
     } 

     //Split the list in two parts and create a new list to store our sorted list 
     LinkedList<Integer> left = mergeSort(new LinkedList<Integer>(unsorted.subList(0, unsorted.size()/2))); 
     LinkedList<Integer> right = mergeSort(new LinkedList<Integer>(unsorted.subList(unsorted.size()/2, unsorted.size()))); 
     LinkedList<Integer> sorted = new LinkedList<Integer>(); 

     //Actual loop for merging the two sublists. Using LinkedLists, this is efficient. (Compared to ArrayList) 
     while(!left.isEmpty() || !right.isEmpty()){ 
      Integer leftInt = left.peekFirst(); 
      Integer rightInt = right.peekFirst(); 

      if(!(leftInt == null) && !(rightInt == null)){ 
       if(leftInt < rightInt){ 
        sorted.add(left.pollFirst()); 
       } 
       else{ 
        sorted.add(right.pollFirst()); 
       } 
      } 
      else if(leftInt == null){ 
       sorted.add(right.pollFirst()); 
      } 
      else{ 
       sorted.add(left.pollFirst()); 
      } 
     } 

     return sorted; 
    } 
} 
+0

haha​​ha如果我的老师没有要求我们只使用ArrayLists和递归,我会这样做的。对不起,我的问题不清楚。我需要的算法是对使用“size”创建并使用Random填充的ArrayList进行排序。该算法需要使用合并排序路径进行排序。我很抱歉,但是我的AP计算机科学老师确实限制了他希望我们完成任务的方式...:/感谢您的帮助 –

+0

从技术上讲,我的解决方案除了ArrayList之外还有其他所有功能......您可以拿我的代码,用ArrayList替换LinkedList,并在while循环中,可以使用ArrayList.get(0)代替LinkedList.peekFirst(),而使用ArrayList.remove(0)代替LinkedList.pollFirst()。那会怎么样? – Dyrborg

+0

或者它有点复杂,因为.get(0)会抛出一个异常,如果列表是空的......但它可以用一点点黑客...和可怕的无效。我不明白为什么你的AP计算机科学老师会强迫你在编程和学习方面做得不好。自从我开始学习计算机科学以来,我从未受到过这样的限制。 – Dyrborg