2014-02-14 93 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