Java递归:按引用传递
我意识到这对Java程序员来说是一个激烈争论、有争议的话题,但我相信我的问题有点独特。我的算法需要通过引用传递。我正在对一棵普通树(即n个子树)进行顺时针/逆时针的预顺序遍历,以分配虚拟(x,y)坐标。这仅仅意味着我在访问树的节点时对它们进行计数(并标记)Java递归:按引用传递,java,pass-by-reference,graph-theory,pass-by-value,Java,Pass By Reference,Graph Theory,Pass By Value,我意识到这对Java程序员来说是一个激烈争论、有争议的话题,但我相信我的问题有点独特。我的算法需要通过引用传递。我正在对一棵普通树(即n个子树)进行顺时针/逆时针的预顺序遍历,以分配虚拟(x,y)坐标。这仅仅意味着我在访问树的节点时对它们进行计数(并标记) /** * Generates a "pre-ordered" list of the nodes contained in this object's subtree * Note: This is counterc
/**
* Generates a "pre-ordered" list of the nodes contained in this object's subtree
* Note: This is counterclockwise pre-order traversal
*
* @param clockwise set to true for clockwise traversal and false for counterclockwise traversal
*
* @return Iterator<Tree> list iterator
*/
public Iterator<Tree> PreOrder(boolean clockwise)
{
LinkedList<Tree> list = new LinkedList<Tree>();
if(!clockwise)
PreOCC(this, list);
else
PreO(this,list);
count = 0;
return list.iterator();
}
private void PreOCC(Tree rt, LinkedList<Tree> list)
{
list.add(rt);
rt.setVirtual_y(count);
count++;
Iterator<Tree> ci = rt.ChildrenIterator();
while(ci.hasNext())
PreOCC(ci.next(), list);
}
private void PreO(Tree rt, LinkedList<Tree> list, int count)
{
list.add(rt);
rt.setX_vcoordinate(count);
Iterator<Tree> ci = rt.ReverseChildrenIterator();
while(ci.hasNext())
PreO(ci.next(), list, ++count);
}
这里还有一句话可以更好地解释x,y坐标。
顶点。顶点的y坐标
逆时针计算
T(T)顶点的预排序
排序从0到n进行编号−
1) ,将它们用作的x坐标
顶点
按顺时针方向计算
T(序)的顶点是
从0到n编号− 1) ,将它们用作
顶点的y坐标
Java的传递值,始终适用于原语和对象。它是为非原语传递的引用,因此您可以更改它们指向的对象的状态,但不能更改引用本身 James Gosling在《Java编程语言》一书中写道: “…只有一个参数 Java中的传递模式-按值传递- 这让事情变得简单……” 我认为这是这方面的最终权威 我意识到这对Java程序员来说是一个激烈争论、有争议的话题
不,没有争论。詹姆斯·戈斯林从一开始就将这一点融入到语言中。如果你认为这是有争议的,那你就很不幸地被蒙蔽或无知了。事实上,在Java中有一种通过引用传递的方法:
class Pointer {
private Object ptr;
public Pointer(Object v) { set(v); }
public void set(Object v) { ptr = v; }
public Object get() { return ptr; }
}
你使用它们:
public void swap(Pointer a, Pointer b) {
Object tmp = a.get();
a.set(b.get());
b.set(tmp);
}
然后像这样进行呼叫交换:
public static void main(String[] args) {
Integer one = 1;
Integer two = 2;
Pointer pone; pone.set(one);
Pointer ptwo; ptwo.set(two);
swap(pone, ptwo);
System.out.println((Integer) pone.get());
System.out.println((Integer) ptwo.get());
}
不过,如果你真的这么做,那么你可能是疯了,或者只是还没有用Java思考。你不需要通过引用传递,你需要一个有副作用的函数。通过引用将是实现这一目标的一种方法;使用可变对象作为函数参数将是另一种选择
private void PreO(Tree rt, LinkedList<Tree> list, int[] count)
{
list.add(rt);
rt.setX_vcoordinate(count[0]);
Iterator<Tree> ci = rt.ReverseChildrenIterator();
while(ci.hasNext()) {
++count[0];
PreO(ci.next(), list, count);
}
}
private void PreO(树rt、链接列表、int[]计数)
{
列表。添加(rt);
rt.setX_vcoordinate(计数[0]);
迭代器ci=rt.ReverseChildrenIterator();
while(ci.hasNext()){
++计数[0];
PreO(ci.next(),list,count);
}
}
我同意。这让我们更难理解在这里该做什么!Nathan你确定你正在建造的树有你想要的结构吗?我看不出节点的预顺序遍历是如何以012345的顺序访问它们的。@matt:我不是按这个顺序访问它们的。访问节点的顺序为顶行。我将发布所有这些代码,因为它似乎让很多人感到困惑。好吧,我理解这一点,但这如何帮助我解决我的问题?提出这个问题的原因不是为了引发辩论,而是为了解决我提出的问题。令人遗憾的是,存在着辩论——当然,一方是无知的。就在昨晚,一个随机的家伙给我发了一封电子邮件,试图让我相信Java总是使用pass-by-reference:(对我来说,这就像神创论和进化论:两者的权重并不相等。@Nathan-对不起,你的问题措辞让人觉得你不仅认为Java是通过引用传递的,而且它是你问题的解决方案。如果你不相信,我会编辑你的措辞。我也会让你的问题更清楚,因为我不相信用递归来进行遍历通常是在java中完成的。也许还有其他的东西你错过了。我想它们是差不多的。很明显,这实际上不是在做引用。它是通过额外的间接引用来模拟引用的。我不是说它不起作用,只是它不像是在改变语言。s传递方案:)这不是按引用传递-抱歉。@duffymo:是的,它不是按引用传递,它更类似于按指针传递。如果将所有a.get()
替换为*a
和a.set(…)
使用*a=…
,您将从C/C++中获得更熟悉的pass-by指针。指针通常被认为是一种特定形式的引用,因此pass-by-pointer是一种特定类型的pass-by-reference(尽管一些纯粹主义者可能不同意,因为指针本身仍然是按值传递的)@duffymo:还有,你需要一点幽默感;)当我看到一些幽默的东西时,我会笑。如果你用这段代码来表达你的苦涩的一面,恐怕是这样,互联网和浏览器正在过滤掉它。
public static void main(String[] args) {
Integer one = 1;
Integer two = 2;
Pointer pone; pone.set(one);
Pointer ptwo; ptwo.set(two);
swap(pone, ptwo);
System.out.println((Integer) pone.get());
System.out.println((Integer) ptwo.get());
}
private void PreO(Tree rt, LinkedList<Tree> list, int[] count)
{
list.add(rt);
rt.setX_vcoordinate(count[0]);
Iterator<Tree> ci = rt.ReverseChildrenIterator();
while(ci.hasNext()) {
++count[0];
PreO(ci.next(), list, count);
}
}