题意:输入一个n,按从小到大的顺序输出从0到1之间的所有分母不大于n的最简分数。
比较容易想到的是排序。可以用结构体表示一个分数,将所有符合条件的分数都存到数组里,然后sort一下,输出就行。注意cmp函数的写法
bool cmp(node x,node y)
{
return x.a*y.b<x.b*y.a; //比较两个分数的大小,交叉相乘
}
最近刚学了二叉树,可以用二叉查找树,实现插入排序。
0/1和1/1这两个值只能逼近不能达到,直接输出即可。
根据二叉查找树的性质,显然1/2是该树的head。
然后分子分母从小到大,往树里进行插入。如果发现树中已有相同的值,说明该分数不是最简,而且已经有最简的在树里了,直接pass掉这个分数即可。
最后,中序遍历输出即可。
#include <cstdio>
#include <cstring>
using namespace std;
struct Node
{
int up;
int down;
Node *left;
Node *right;
Node *p;
Node()
{
left=NULL;
right=NULL;
p=NULL;
}
}*head;
void Insert(Node* t)
{
Node *th;
th=head;
Node* y;
y=NULL;
while(th!=NULL)
{
y=th;
if(t->up*th->down>t->down*th->up)
{
th=th->right;
}
else if(t->up*th->down==t->down*th->up)
{
return; //相同元素,说明不是最简分数,并且前面肯定出现过了。
}
else th=th->left;
}
t->p=y; //让t的p指针指向y
if(y==NULL)//如果树为空。本题不用考虑。
{
head=t;
}
else if(t->up*y->down > t->down*y->up) //把待插结点,插在y的下面(让y指向t)。
{
y->right=t;
}
else y->left=t;
}
void inorder(Node* head)
{
Node* th;
th=head;
if(th!=NULL)
{
inorder(th->left);
printf("%d/%d\n",th->up,th->down);
inorder(th->right);
}
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
printf("0/1\n");
if(n==1)
{
printf("1/1\n\n");
continue;
}
head=new Node();
head->up=1;
head->down=2;
for(int i=2; i<=n; i++)
{
for(int j=1; j<i; j++)
{
Node *t;
t=new Node();
t->up=j;
t->down=i;
Insert(t);
}
}
inorder(head);
printf("1/1\n\n");
}
return 0;
}