这个代码,在每个循环周期中创建两个较小的段,它添加到数字0.问题是,如果你拆分50你得到25和25如果你拆分51你也得到25.这个x和y应该代表数组索引,所以他们从0开始。如果你知道更好的迭代算法(不能使用递归)我会很高兴看到它,但我真的想以这种方式解决这个问题(除非它无法完成)。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int n;
int a, b, x, r, y;
printf("Enter N: ");
scanf("%d", &n);
a = 0;
b = n - 1;
x = a;
y = b;
r = b;
printf(" %2d %2d\n", a, b);
while(b > 1)
{
r /= 2;
while(x < n - 1)
{
printf(" %2d ", x);
y = x + r; //if(something) y = x + r - 1;
printf("%2d", y); //else y = x + r;
x = y + 1;
}
x = a;
b = r;
y = b;
putchar('\n');
}
return 0;
}
输出:
Enter N: 50
0 49
0 24 25 49
0 12 13 25 26 38 39 51
0 6 7 13 14 20 21 27 28 34 35 41 42 48
0 3 4 7 8 11 12 15 16 19 20 23 24 27 28 31 32 35 36 39 40 43 44 47 48 51
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
Press [Enter] to close the terminal ...
答案 0 :(得分:2)
谷歌搜索quicksort。您将找到许多使用此技术的代码示例。
答案 1 :(得分:2)
这是广度优先的遍历问题,应该使用队列来实现。我不认为有一种简单的方法来实现广度优先递归,因此迭代方法必须这样做。以下是一个粗略的算法:
1)创建两个队列q
和p
,其中包含您的初始范围[a, b]
。
2)虽然p
不为空,但请将某个元素从p
出列并打印出来。
3)虽然q
不为空,但会从[i, j]
将某个元素q
出列,并将两个新范围[i, (i + j) / 2]
和[(i + j) / 2 + 1, j]
排入p
}。
4)将p
复制到q
。
5)如果q
的大小为a + b + 1
,那么您就完成了。否则,请返回步骤2.
这是我在C#中的实现:
using System;
using System.Collections.Generic;
struct Pair
{
public int a;
public int b;
public Pair(int a, int b)
{
this.a = a;
this.b = b;
}
}
class Program
{
static void Main()
{
Console.Write("Enter a number: ");
int size = int.Parse(Console.ReadLine());
Queue<Pair> queue = new Queue<Pair>();
queue.Enqueue(new Pair(0, size));
bool lastRound = false;
do
{
if (queue.Count == size + 1)
{
lastRound = true;
}
Queue<Pair> temporary = new Queue<Pair>(queue);
while (temporary.Count > 0)
{
Pair pair = temporary.Dequeue();
if (pair.b - pair.a == 0)
{
Console.Write("{0} ", pair.a);
}
else
{
Console.Write("{0}-{1} ", pair.a, pair.b);
}
}
Console.WriteLine();
while (queue.Count > 0)
{
Pair pair = queue.Dequeue();
if (pair.b - pair.a == 0)
{
temporary.Enqueue(new Pair(pair.a, pair.b));
}
else
{
temporary.Enqueue(new Pair(pair.a, (pair.a + pair.b) / 2));
temporary.Enqueue(new Pair((pair.a + pair.b) / 2 + 1, pair.b));
}
}
queue = temporary;
} while (!lastRound);
}
}
这是它的输出:
Enter a number: 20
0-20
0-10 11-20
0-5 6-10 11-15 16-20
0-2 3-5 6-8 9-10 11-13 14-15 16-18 19-20
0-1 2 3-4 5 6-7 8 9 10 11-12 13 14 15 16-17 18 19 20
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
答案 2 :(得分:0)
当你分割数字时,你需要决定是否有余数(取决于你分裂的数字是奇数还是偶数)。
您需要以不同方式处理两种不同的情况。您还必须决定将额外号码放在哪里(在前半部分或后半部分)。
也许可能的修改就是有两个r来跟踪这两半。
答案 3 :(得分:0)
问题的根源是无法为每次迭代计算固定的跳转大小(r)。一个常数 每次迭代的r仅在起始编号时起作用 是两个的力量(尝试从64开始,你会发现它一切都按你的意愿工作)。对于任何其他数字 跳跃大小(r)可以是r或r + 1,具体取决于是否 先前的迭代将当前范围划分为偶数或奇数个元素。所以 在整个迭代过程中,r的值可能不是常数。
只要您看到当前迭代依赖于先前迭代的结果,就会弹出“stack”或“recursion”字样 作为即时解决方案这是因为需要先前的状态信息来解决问题。
对你的问题可能有一个纯粹的迭代解决方案,但我认为它会带来一些有趣的 数学或额外的内存来维护状态信息。