如何让我的递归函数在进入下一级循环之前读取每个新实例?

How do I make my recursive function read every new instance before proceeding to the next level of the loop?

我必须模拟粒子分裂成粒子。 我的模拟函数决定有多少粒子从分裂中脱落。 然后根据它决定分裂成多少个粒子调用自己进行模拟。

代码如下:

void Reaction::Simulate(double energy,  TwoVector position )
{
    int RandomNumber= qrand() %3+1;//starting particle
    energy = energy/RandomNumber; // change energy for each reaction
    double time=1.0;
    std::cout<<RandomNumber<<std::endl;

    if (RandomNumber==1){
        LightParticle* i=new LightParticle(energy, position);
        int speed = 3;
        i->SimulatePath(time, speed, i->GetPosition());
        i->GetPosition().Print();
        energy--;
        Simulate(energy, i->GetPosition());
    }
    else if (RandomNumber==2){
        MediumParticle* j=new MediumParticle(energy, position);
        MediumParticle* k=new MediumParticle(energy, position);
        int speed = 2;

        j->SimulatePath(time,speed, position);
        k->SimulatePath(time,speed, position);

        j->GetPosition().Print();
        k->GetPosition().Print();

        Simulate(energy, j->GetPosition());
        Simulate(energy, k->GetPosition());
    }
    else if (RandomNumber==3) {
        HeavyParticle* l = new HeavyParticle(energy, position);
        HeavyParticle* m = new HeavyParticle(energy, position);
        HeavyParticle* n = new HeavyParticle(energy, position);
        int speed = 1;

        l->SimulatePath(time,speed, position);
        l->GetPosition().Print();

        m->SimulatePath(time,speed, position);
        m->GetPosition().Print();

        n->SimulatePath(time,speed, position);
        n->GetPosition().Print();

        Simulate(energy, l->GetPosition());
        Simulate(energy, m->GetPosition());
        Simulate(energy, n->GetPosition());
    }
    else return;
}

从代码中可以看出,它只会走到一条路径的最深层,然后才会移动到下一条路径。我怎样才能让它同时遵循每条路径?

qsrand() 在未使用值初始化时将始终保持相同的值。

qsrand(time(NULL));
ID=qrand() % 3;
qDebug << “ID random: “ << ID;

qsrand(static_cast<quint64>(QTime::currentTime().msecsSinceStartOfDay()));
array<int, 3> arr = {qrand(), qrand(), qrand()};
for(auto i : arr)
    cout << i << endl;

我不知道你是否真的想同时走所有的路。在我看来,问题在于打破循环。这应该像

一样提供
void Reaction::Simulate(double energy,  TwoVector position )
{
    if (energy < minimalEnergy) return;
    if (isAtGround(position)) return;

    int RandomNumber= qrand() %3+1;//starting particle
    // all the rest, but please repair the memory leaks!
}

当你的粒子不能进一步分裂时,你应该提供一个函数 bool isAtGround(const TwoVector& position) 和一个 minimalEnergy (典型的限制是最轻的粒子质量)。如果能量太小,您可能不会返回,而是沿着粒子路径到达地面。但这取决于你的具体任务。

顺便说一句,我觉得能量只在 RandomNumber==1 期间降低了,这对我来说似乎很奇怪。

首先,使用此代码,您将几乎立即发生堆栈溢出。

您的基本代码路径在伪代码中如下所示:

func() {
    path = RAND(1, 3);
    if(path == 1) /*DO STUFF*/ func();
    else if(path == 2) /*DO STUFF*/ func();
    else /*DO STUFF*/ func();
}

因此,无论这些步骤是否 "simultaneous",您的代码永远不会终止。如果您希望代码最终停止,您应该让随机数处于不仅输出数字 [1, 3].

的范围内
int RandomNumber= qrand() %4; //Will stop when RandomNumber == 0

如果有更明确的递归停止条件(例如 energy == 0 时),您需要编写代码。

您的第二个问题是您不清楚执行所有这些步骤的意思"simultaneously"。您是否希望所有路径在多个线程中并行执行?

你需要这样写:

std::thread t1([=]{
    LightParticle* i=new LightParticle(energy, position);
    int speed = 3;
    i->SimulatePath(time, speed, i->GetPosition());
    i->GetPosition().Print();
    energy--;

    if(condition_to_continue_recursing()) {
        Simulate(energy, i->GetPosition());
    }
});
std::thread t2([=]{
    MediumParticle* j=new MediumParticle(energy, position);
    MediumParticle* k=new MediumParticle(energy, position);
    int speed = 2;

    j->SimulatePath(time,speed, position);
    k->SimulatePath(time,speed, position);

    j->GetPosition().Print();
    k->GetPosition().Print();

    if(condition_to_continue_recursing()) {
        Simulate(energy, j->GetPosition());
        Simulate(energy, k->GetPosition());
    }
});
std::thread t3([=]{
    HeavyParticle* l = new HeavyParticle(energy, position);
    HeavyParticle* m = new HeavyParticle(energy, position);
    HeavyParticle* n = new HeavyParticle(energy, position);
    int speed = 1;

    l->SimulatePath(time,speed, position);
    l->GetPosition().Print();

    m->SimulatePath(time,speed, position);
    m->GetPosition().Print();

    n->SimulatePath(time,speed, position);
    n->GetPosition().Print();

    if(condition_to_continue_recursing()) {
        Simulate(energy, l->GetPosition());
        Simulate(energy, m->GetPosition());
        Simulate(energy, n->GetPosition());
    }
});

t1.join();
t2.join();
t3.join();

但是condition_to_continue_recursing()是什么就得由你来决定了;我对您的总体任务了解不多,无法回答这个问题。此外,如果您的 condition_to_continue_recursing 非常重要,这将产生荒谬数量的线程;使用线程池可能是首选。所有这一切都取决于您决定使用线程是完成此类任务的理想选择,但(对我而言)这并不明显。

你的第三个问题是这个代码片段中充斥着相当严重的设计错误。

HeavyParticle* l = new HeavyParticle(energy, position);
HeavyParticle* m = new HeavyParticle(energy, position);
HeavyParticle* n = new HeavyParticle(energy, position);

这些指针中的每一个都会泄漏。由于对象仅在定义它们的范围内使用,因此使用 std::unique_ptr 可能是理想的:

std::unique_ptr<HeavyParticle> l = std::make_unique<HeavyParticle>(energy, position);
std::unique_ptr<HeavyParticle> m = std::make_unique<HeavyParticle>(energy, position);
std::unique_ptr<HeavyParticle> n = std::make_unique<HeavyParticle>(energy, position);

编辑:或者,没有充分的理由让您一开始就应该在这种情况下使用指针。以下代码可以完美运行,没有内存泄漏或更改代码的功能:

HeavyParticle l(energy, position);
HeavyParticle m(energy, position);
HeavyParticle n(energy, position);
int speed = 1;

l.SimulatePath(time,speed, position);
l.GetPosition().Print();

m.SimulatePath(time,speed, position);
m.GetPosition().Print();

n.SimulatePath(time,speed, position);
n.GetPosition().Print();

Simulate(energy, l.GetPosition());
Simulate(energy, m.GetPosition());
Simulate(energy, n.GetPosition());

您可能也不应该使用 qrand

std::default_random_engine engine(std::random_device()());

void Reaction::Simulate(double energy,  TwoVector position )
{
    std::uniform_int_distribution<int> distribution(0, 3);
    int RandomNumber = distribution(engine);
    /*... Whatever*/

更好的设计是将引擎传递给函数。

选择:

std::default_random_engine engine(std::random_device()());

void Reaction::Simulate(double energy,  TwoVector position )
{
    if(energy <= 0) return;
    std::uniform_int_distribution<int> distribution(1, 3);
    int RandomNumber = distribution(engine);
    /*... Whatever*/

这还有很多内容,但还有很多内容需要深入研究。希望这会是一个好的起点。