2010-04-27 84 views
4

我有以下函數來排序一個無序數組,以便在前面有偶數,在後面有奇數。有沒有辦法讓它完成而不使用任何循環?使用遞歸排序

//front is 0, back =array.length-1; 
arrangeArray (front, back); 

public static void arrangeArray (int front, int back) 
{ 
    if (front != back || front<back) 
    { 
     while (numbers [front]%2 == 0) 
      front++; 


     while (numbers[back]%2!=0) 
      back--; 


     if (front < back) 
     { 
      int oddnum = numbers [front]; 
      numbers[front]= numbers[back]; 
      numbers[back]=oddnum; 

      arrangeArray (front+1, back-1); 
     } 
    } 
} 

回答

0

你想要做什麼是

arrangeArray(front, back, bool recursed=false) { 
    if (recursed) { 
     arrangeArray(front, back/2, true); 
     return arrangeArray(back/2, back, true); 
    } 
    // Do stuff here. 
} 
+0

嗯......如果你用record = false來調用它,它什麼也不做。如果你用recursed = true調用它,它將永遠遞歸。 – Oddthinking 2010-04-27 01:51:12

3

Mergesort是相當瑣碎的代碼,而循環:

​​

我會離開使它排序偶/奇作爲一個練習讀者:)

(聽起來像家庭作業)

+0

我不認爲合併排序的結構是這個問題的正確結構。 這是向中間遞歸,沒有分而治之,只是純迭代遞歸。 – 2010-04-27 01:17:25

+0

Charles:如何在中間分割數組,然後使用兩個遞歸遞歸,然後合併它們,而不是分而治之的算法? – hzap 2010-04-27 01:30:31

+0

我是說這個問題不需要分而治之(合併排序IS),分而治之的問題通常是在O(nlogn)中解決的,因爲這個可以在O(n) – 2010-04-27 01:33:03

2

當你做遞歸時,你有一個基礎步驟和一個遞歸步驟。

在這種情況下,基礎條件是當前==返回時,因爲您從邊緣開始,最終在中間。當你到達中間時,你知道它已經完成。

在你做遞歸步驟之前,你必須做一些排序。你只做一步一步的排序,所以現在只需處理array [front]和array [back]中的元素。將這些人安排在正確的地方後,請進行遞歸調用。

你最終的東西是這樣的:

public static void arrangeArray (int front, int back) 
{ 
    if(front >= back) return; 
    int f = numbers[front]; 
    int b = numbers[back]; 
    if(f%2 == 0) { 
     front++; 
    } else { 
     numbers[back] = f; 
     back--; 
    } 
    if (b%2 == 0) { 
     numbers[front] = b; 
     front++; 
    } else { 
     back--; 
    } 
    arrangeArray(front, back);           
} 

這是未經測試,可能是邊界條件不工作,但它是一個良好的開端:)

2

那不是簡單地:

//front is 0, back =array.length-1; 
arrangeArray (front, back); 

public static void arrangeArray (int front, int back) 
{ 
    if (front != back || front<back) 
    { 
     if (numbers [front]%2 == 0) 
      arrangeArray (front+1, back); 
     else 
     if (numbers[back]%2!=0) 
      arrangeArray (front, back-1); 
     else 
     if (front < back) 
     { 
      int oddnum = numbers [front]; 
      numbers[front]= numbers[back]; 
      numbers[back]=oddnum; 

      arrangeArray (front+1, back-1); 
     } 
    } 
} 

1

我可以推薦這個Python代碼片段來激發高層次的思考嗎?

compare = lambda x,y: x - y if x%2 == y%2 else y%2 - x%2 
>>> sorted([3,4,2,1,5,6,7,90,23,44], cmp=compare) 
[1, 3, 5, 7, 23, 2, 4, 6, 44, 90] 

我認爲需要建立一個比較函數,返回負數,0和正數,並使用它。

0

以下內容應該具有啓發性。這是一個遞歸的O(N)解決方案,它可以重新排列前面的偶數和後面的奇數,但不會做任何排序。

static boolean isEven(int n) { 
    return (n & 1) == 0; 
} 
static boolean isOdd(int n) { 
    return !isEven(n); 
} 
static int[] swapped(int[] nums, int i, int j) { 
    int t = nums[i]; 
    nums[i] = nums[j]; 
    nums[j] = t; 
    return nums; 
} 
static int[] arrange(int[] nums, int lo, int hi) { 
    return 
     (lo >= hi) ? nums : 
     (isEven(nums[lo])) ? arrange(nums, lo + 1, hi) : 
     (isOdd(nums[hi])) ? arrange(nums, lo, hi - 1) : 
     arrange(swapped(nums, lo, hi), lo + 1, hi - 1); 
} 
static void evenOddSort(int... nums) { 
    System.out.println(java.util.Arrays.toString(
     arrange(nums, 0, nums.length - 1) 
    )); 
} 
public static void main(String[] args) { 
    evenOddSort(1,3,5,7,2,4,6); 
} // prints "[6, 4, 2, 7, 5, 3, 1]" 

我認爲三元操作使得遞歸流更自然,但如果你不與它的工作原理是舒服,你可以用傳統的if-else

static int[] arrange(int[] nums, int lo, int hi) { 
    if (lo >= hi) { 
     return nums; 
    } else if (isEven(nums[lo])) { 
     return arrange(nums, lo + 1, hi); 
    } else if (isOdd(nums[hi])) { 
     return arrange(nums, lo, hi - 1); 
    } else { 
     return arrange(swapped(nums, lo, hi), lo + 1, hi - 1); 
    } 
} 
+0

濫用嵌套的三元運算符。 :P – Stephen 2010-04-27 01:47:43

+0

@Stephen:我不同意。三元運算符是右聯合的是有原因的,它允許這種表達級別的if-else類似於結構。 – polygenelubricants 2010-04-27 01:51:28

+0

我同意斯蒂芬。只是因爲你可以不用括號寫它並不意味着你應該。表達式x^a + b^c + d是完全明確的,但那些不瞭解優先規則的人會非常困惑。 – 2010-04-27 07:08:01