这道题,一开始我也是想着先列出所有的数,然后使用快速排序,不过在网上看见一个很不错的解决方法,大概代码如下:
void print(n1,n2,d1,d2)
{
print(n1,n1+n2,d1,d1+d2);
输出 n1+n2,d1+d2;
print(n1+n2,n2,d1+d2,d2);
}
初始时调用
print(0,1,1,1);
下面做一下解释,print函数是输出一个分数,分子是n1+n2,分母是d1+d2,
但是在输出这个分数前我们要判断一下有没有比这个分数还要小的应该输出的分数,如果有则先输出比它小的分数,也就是第一次递归调用自己的部分,然后再输出自己,最后输出比自己大的所有分数(对应第二次递归调用时),这样一来一开始我们调用print输出1/2就可以顺序输出所有的分数了,也就是题目的解
那么为什么分数(n1,n1+n2,d1,d1+d2)一定比(n1,n2,d1,d2)小呢?为什么(n1+n2,n2,d1+d2,d2)一定比(n1,n2,d1,d2)大呢?下面证明前面这个问题,后一个略同。下面的所有定理都是仅针对第一次递归调用的。
注意有关系 n1/n2 < d1/d2(第一次调用print(0,1,1,1)时自然是成立的),此时我们要证明一下调用
print(n1,n1+n2,d1,d1+d2)后关系n1/(n1+n2) < d1/(d1+d2) <式1>仍然成立,这里的证明读者可以通过对式1两边分别乘上(n1+n2)(d1+d2)并移动项得到n1/n2 < d1/d2而得,所以就不多说了
也就是说n1/n2 < d1/d2 总是成立的,再注意看,第一次递归调用后得到的新分数是(n1+n2+n1)/(d1+d2+d1),然后我们要证明这个新分数比老分数(n1+n2)/(d1+d2)小,
同样也可以通过化简 (n1+n2+n1)/(d1+d2+d1) < (n1+n2)/(d1+d2) 而得到n1/n2 < d1/d2 来证明
说得虽然有点乱,不过我想读者能看得懂了,虽然我还不知道怎么证明每一次递归调用得到的分数都是最简化的,但是这足够我们理解为什么这个方法可行了,基本思想就是递归效用,先处理比我小的,然后处理我,最后处理比我大的,这样一来就能得到一个从小到大的序列

Code

/**//*
ID: sdjllyh1
PROG: frac1
LANG: JAVA
complete date: 2008/11/30
author: LiuYongHui From GuiZhou University Of China
more article: www.cnblogs.com/sdjls
*/

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

public class frac1


{
private static int n;
private static int[] numerator = new int[8000];
private static int[] denominator = new int[8000];
private static int ansCount = 0;

public static void main(String[] args) throws IOException

{
init();
run();
output();
System.exit(0);
}

private static void run()

{
numerator[ansCount] = 0;
denominator[ansCount] = 1;
ansCount++;

solve(0, 1, 1, 1);

numerator[ansCount] = 1;
denominator[ansCount] = 1;
ansCount++;
}

private static void solve(int n1, int n2, int d1, int d2)

{
if (d1 + d2 > n)

{
return;
}
solve(n1, n1 + n2, d1, d1 + d2);

numerator[ansCount] = n1 + n2;
denominator[ansCount] = d1 + d2;
ansCount++;

solve(n1 + n2, n2, d1 + d2, d2);
}

private static void init() throws IOException

{
BufferedReader f = new BufferedReader(new FileReader("frac1.in"));
n = Integer.parseInt(f.readLine());
f.close();
}

private static void output() throws IOException

{
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("frac1.out")));
for (int i = 0; i < ansCount; i++)

{
out.println(numerator[i] + "/" + denominator[i]);
}
out.close();
}
}