C ++中的递归分解

时间:2012-12-14 13:29:04

标签: c++

我正在努力学习递归。在基础案例下面的代码中分解练习以绘制递归树时遇到问题包括函数window.drawPolarLine(branchbase,length,angle),它返回刚绘制的分支末尾的GPoint(x和y)。任何递归解决方案都必须跟踪大量的GPoints。如果那应该发生在堆栈帧中,或者我应该使用向量来存储它们,我无法解决。使用矢量似乎正在沿着迭代解决方案的道路前进?

无论如何,到目前为止,这是我非常混乱的代码;

/**
 * File: trees.cpp
 * ---------------
 * Draws a recursive tree as specified in the Assignment 3 handout.
 */

#include <string>    // for string
#include <iostream>  // for cout, endl
using namespace std;

#include "console.h" // required of all CS106 C++ programs
#include "gwindow.h" // for GWindow class and its setTitle, setColor, and drawPolarLine methods
#include "gtypes.h"  // for GPoint class
#include "random.h"  // for randomChance function

const static double kWindowWidth = 600;
const static double kWindowHeight = 600;
const static string kWindowTitle = "Recursive Trees";
const static double kTrunkLength  = kWindowHeight/4;
const static double kShrinkFactor = 0.70;
const static int kBranchAngleSeparation = 15;
const static int kTrunkStartAngle = 90;
const static string kLeafColor = "#2e8b57";
const static string kTrunkColor = "#8b7765";
const static double kBranchProbability = 1.0;

static GPoint drawTree(GWindow& window, int order, GPoint branchBase, double length, int angle, Vector<GPoint>& branches);

const static int kHighestOrder = 5;
int main() {
    GWindow window(kWindowWidth, kWindowHeight);
    window.setWindowTitle(kWindowTitle);
    cout << "Repeatedly click the mouse in the graphics window to draw " << endl;
    cout << "recursive trees of higher and higher order." << endl;
    GPoint trunkBase(window.getWidth()/2, window.getHeight());
    Vector<GPoint> branches;
    for (int order = 0; order <= kHighestOrder; order++) {
        waitForClick();
        window.clear();
        drawTree(window, order, trunkBase, kTrunkLength, kTrunkStartAngle, branches);
    }

    cout << endl;
    cout << "All trees through order " << kHighestOrder << " have been drawn." << endl;
    cout << "Click the mouse anywhere in the graphics window to quit." << endl;
    waitForClick();
    return 0;
}

static GPoint drawTree(GWindow& window, int order, GPoint branchbase, double length, int angle, Vector<GPoint>& branches) {
    if (order == 0) {

        GPoint base = window.drawPolarLine(branchbase, length, angle);
        branches.add(base);
        return branchbase;
    }

        window.setColor(order < 2 ? kLeafColor : kTrunkColor);

        branchbase = branches.get(order - 1);
        drawTree(window, order - 1, branchbase, length * kShrinkFactor, angle - 45, branches);
        drawTree(window, order - 1, branchbase, length * kShrinkFactor, angle - 30, branches);
        drawTree(window, order - 1, branchbase, length * kShrinkFactor, angle - 15, branches);
        drawTree(window, order - 1, branchbase, length * kShrinkFactor, angle, branches);
        drawTree(window, order - 1, branchbase, length * kShrinkFactor, angle + 15, branches);
        drawTree(window, order - 1, branchbase, length * kShrinkFactor, angle + 30, branches);
        drawTree(window, order - 1, branchbase, length * kShrinkFactor, angle + 45, branches);


        return drawTree(window, order - 1, branchbase, length * kShrinkFactor, angle, branches);
    }
    // update this function to wrap around another version of drawTree, which
    // recursively draws the tree of the specified order....

1 个答案:

答案 0 :(得分:0)

此问题需要与经典递归示例(如排序)略有不同的方法,其中问题集在每次递归时都会减少,并且存在自然限制(问题大小&lt; = 1)。

有了这个问题,信息量随着树的顺序呈指数增长。这使得通过首先绘制二阶树并让函数返回到那些分支结束的位置(以及以哪个角度)来绘制三阶树是不切实际的,因此您可以将三阶分支添加到它。

对于这类问题,编写这样的递归函数要容易得多:

void drawTreeOrder(GWindow& window, int curr_order, int max_order, GPoint branchBase, double length, int angle)
{
    /* Check if there is more work to do */
    if (curr_order >= max_order)
    {
        return;
    }

    /* Draw a branch */
    window.setColor(curr_order - max_order < 2 ? kLeafColor : kTrunkColor);
    GPoint end = window.drawPolarLine(branchBase, length, angle);

    /* Draw the higher-order branches starting from the current one */
    drawTreeOrder(window, order + 1, max_order, end, length * kShrinkFactor, angle - 45, branches);
    drawTreeOrder(window, order + 1, max_order, end, length * kShrinkFactor, angle - 30, branches);
    drawTreeOrder(window, order + 1, max_order, end, length * kShrinkFactor, angle - 15, branches);
    drawTreeOrder(window, order + 1, max_order, end, length * kShrinkFactor, angle, branches);
    drawTreeOrder(window, order + 1, max_order, end, length * kShrinkFactor, angle + 15, branches);
    drawTreeOrder(window, order + 1, max_order, end, length * kShrinkFactor, angle + 30, branches);
    drawTreeOrder(window, order + 1, max_order, end, length * kShrinkFactor, angle + 45, branches);
}

/* Convenience function, so the caller does not have to bother with curr_order */
void drawTree(GWindow& window, int max_order, GPoint branchbase, double length, int angle)
{
    drawTreeOrder(window, 0, max_order, branchBase, length, angle);
}