PHP - 无需通过引用传递值

时间:2015-08-09 19:55:02

标签: php recursion

我在零矩阵中有工作功能 flood-fill sa 封闭区域递归,给定区域内的X和Y.

class Game
{
    Bitmap image;

    public Game(Bitmap image)
    {
        this.image = image;
    }
}

...
Bitmap tempConvert;
...
tempConvert = new Bitmap(100, 100);
games.Add(new Game(tempConvert));
tempConvert.Dispose();

因为我递归调用此函数超过 1 时间,所以我不能只返回该函数。我最后还得回来。因此,我必须通过引用传递矩阵,如您所见。否则它将无法工作。

如何更改此代码,以便按值传递矩阵,函数将返回新的充满洪水的矩阵

谢谢!

2 个答案:

答案 0 :(得分:1)

如果更改函数以将数组作为参数,修改并返回,则实际上可以避免使用引用。你所要做的就是记住当你递归地调用它时:

import UIKit
import Foundation

class CollectionViewController: UICollectionViewController, UICollectionViewDataSource, UICollectionViewDelegate, UIGestureRecognizerDelegate {

var name = [String]()
var originalCenter: CGPoint!
var animator: UIDynamicAnimator!

override func viewDidLoad() {
    super.viewDidLoad()

    let width = CGRectGetWidth(collectionView!.frame)
    let layout = collectionViewLayout as! UICollectionViewFlowLayout
    layout.itemSize = CGSize(width: width, height: width + (width / 3))

    name = ["DAN", "DANIELA", "MIRABELA", "ANGELA", "CARTOCEA", "FANDOSAN"]

}

override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    return 1
}

override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return name.count
}

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! UICollectionViewCell

    originalCenter = cell.center
    animator = UIDynamicAnimator(referenceView: cell)

    let names = cell.viewWithTag(1) as! UILabel
    names.text = name[indexPath.row]

    let panLeftRight: UIGestureRecognizer = UIPanGestureRecognizer(target: self, action: "handlePan:")
    panLeftRight.delegate = self
    cell.addGestureRecognizer(panLeftRight)

    return cell
}

func handlePan(sender: UIPanGestureRecognizer) {

    let translation = sender.translationInView(self.view)
    let location = sender.locationInView(self.view)

    var widthForPan = CGRectGetWidth(collectionView!.frame)

    sender.setTranslation(CGPoint(), inView: self.view)

    switch sender.state {

    case .Began:
        if let view = sender.view {
            view.center = CGPoint(x:view.center.x, y:view.center.y)
        }
    case .Changed:
        if let view = sender.view {

            view.center = CGPoint(x:view.center.x + translation.x,
                y:view.center.y)
        }
    case .Ended:
        UIView.animateWithDuration(0.4) {
            if let revine = sender.view {
                revine.center = CGPoint(x: translation.x + widthForPan / 2, y: revine.center.y)
            }
            print(self.originalCenter)
            print(widthForPan)
        }

    default:
        if let view = sender.view {
            view.center = CGPoint(x:view.center.x,
                y:view.center.y)

        }
        sender.setTranslation(CGPointZero, inView: self.view)
    }
}
}

<强>更新

正如@Daniel评论的那样,在执行函数期间,每次执行function MatrixFloodFill(array $matrix, $x, $y) { if($matrix[$x][$y] == 0) { // Modify the matrix $matrix[$x][$y] = 1; // Pass the modified matrix to the recursive call and ... // ... store the value it returns (a modified copy of the matrix) $matrix = MatrixFloodFill($matrix, $x+1, $y); // ... do the same again and again ... $matrix = MatrixFloodFill($matrix, $x-1, $y); $matrix = MatrixFloodFill($matrix, $x, $y+1); $matrix = MatrixFloodFill($matrix, $x, $y-1); } // Return the modified matrix return $matrix; } 块时,行if都会生成矩阵的新副本。只保留最后一个这样的副本(它由函数的最顶层调用返回,并且可能由调用代码保存在变量中),所有其他副本都被销毁。

执行函数期间创建的副本数等于修改的元素数(最多为矩阵中元素的总数)。如果这个数字很大,那么脚本会花费大量的处理时间来创建许多副本并丢弃所有副本,但最后一个副本。

通过值传递矩阵的唯一优点是代码清洁度和可测试性(顺便说一下,这不是一件小事)。但是,如果将原始函数(使用引用)标记为实现细节(此处的语言对您没有帮助,您可以在函数的文档中解释这一点),则可以保持可测试性和清洁性,编写一个包装函数来获取矩阵值,调用引用函数,然后返回更新的矩阵,只使用包装函数(它是公共接口)。

更好的是,您应该将数据和代码嵌入到类中。它还应该存储矩阵的维度(你发布的代码不检查它们,递归永远不会停止;我假设发布的代码是一个最小的例子,真实的代码正确处理矩阵的维度。)

答案 1 :(得分:1)

axiac发布了一个问题的答案,该答案产生了一个递归函数,该函数不通过引用取矩阵。这样可行,但效率低得多。

我建议你保留原来的方法,然后添加另一个包装器:

function MatrixFloodFillRef(&$matrix, $x, $y)
{
    if($matrix[$x][$y] == 0)
    {
        $matrix[$x][$y] = 1;
        MatrixFloodFillRef($matrix, $x+1, $y);
        MatrixFloodFillRef($matrix, $x-1, $y);
        MatrixFloodFillRef($matrix, $x, $y+1);
        MatrixFloodFillRef($matrix, $x, $y-1);
    }

    return $matrix;
}

function MatrixFloodFill($matrix, $x, $y)
{
    MatrixFloodFillRef($matrix, $x, $y);

    return $matrix;
}