Java递归:按引用传递

发布于 2024-09-30 10:23:14 字数 2838 浏览 6 评论 0原文

我意识到这对 Java 程序员来说是一个争论激烈、有争议的话题,但我相信我的问题有些独特。我的算法需要通过引用传递。我正在对一般树(即n个子树)进行顺时针/逆时针前序遍历以分配虚拟(x,y)坐标。这仅仅意味着我在访问树的节点时对它们进行计数(并标记)。

/**
 * 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);
}

在这里,我生成树的结构:

Tree root = new Tree(new Integer(0));
root.addChild(new Tree(new Integer(1), root));
root.addChild(new Tree(new Integer(2), root));
root.addChild(new Tree(new Integer(3), root));
Iterator<Tree> ci = root.ChildrenIterator();
ci.next();
Tree select = ci.next();
select.addChild(new Tree(new Integer(4), select));
select.addChild(new Tree(new Integer(5), select));

这是我打印遍历节点的顺序以及分配给相应节点的坐标时的输出。

0 3 2 5 4 1
0 1 2 3 4 3

0 1 2 4 5 3
0 1 2 3 4 3

注意:前两行是顺时针前序遍历并赋值x坐标。接下来的两行是逆时针前序遍历并分配它们的 y 坐标。

我的问题是如何读取第二行: 0 1 2 3 4 5

编辑1:这是我用来打印我访问节点的顺序和我分配的坐标的代码。

Iterator<Tree> pre = root.PreOrder(true);
System.out.println("              \t");
while(pre.hasNext())
    System.out.print(pre.next() + "\t");
    
pre = root.PreOrder(true);
System.out.println();
System.out.println("x-coordinates:\t");
while(pre.hasNext())
System.out.print(pre.next().getVirtual_x() + "\t");
    
System.out.println();
System.out.println();
    
Iterator<Tree> preCC = root.PreOrder(false);
System.out.println("              \t");
while(preCC.hasNext())
    System.out.print(preCC.next() + "\t");
    
preCC = root.PreOrder(false);
System.out.println();
System.out.println("x-coordinates:\t");
while(preCC.hasNext())
System.out.print(preCC.next().getVirtual_y() + "\t");

这里还有一个引用可以更好地解释 x,y 坐标。 顶点。顶点的 y 坐标。

计算逆时针方向 T 的顶点的预排序( 排序从 0 到 n 编号 - 1)、使用它们作为 x 坐标 顶点。

计算顺时针预排序 T 的顶点(顺序是 编号从 0 到 n − 1),将它们用作 顶点的 y 坐标。

I realize this is a hotly debated, controversial topic for Java programmers, but I believe my problem is somewhat unique. My algorithm REQUIRES pass by reference. I am doing a clockwise/counterclockwise pre-order traversal of a general tree (i.e. n-children) to assign virtual (x,y) coordinates. This simply means I count (and tag) the nodes of tree I visit as I visit them.

/**
 * 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);
}

Here I generate the structure of the tree:

Tree root = new Tree(new Integer(0));
root.addChild(new Tree(new Integer(1), root));
root.addChild(new Tree(new Integer(2), root));
root.addChild(new Tree(new Integer(3), root));
Iterator<Tree> ci = root.ChildrenIterator();
ci.next();
Tree select = ci.next();
select.addChild(new Tree(new Integer(4), select));
select.addChild(new Tree(new Integer(5), select));

And here is my output when I print the order the nodes are traversed and the coordinates it assigns to the respective node.

0 3 2 5 4 1
0 1 2 3 4 3

0 1 2 4 5 3
0 1 2 3 4 3

Note: The first two lines is a clockwise pre-order traversal and assignment of the x-coordinates. The next two lines are a counterclockwise pre-order traversal and assignment of they y-coordinates.

My question is how I can get the second lines to read:
0 1 2 3 4 5

EDIT 1: Here is the code I use to print the order I visit the nodes and the coordinates I assign.

Iterator<Tree> pre = root.PreOrder(true);
System.out.println("              \t");
while(pre.hasNext())
    System.out.print(pre.next() + "\t");
    
pre = root.PreOrder(true);
System.out.println();
System.out.println("x-coordinates:\t");
while(pre.hasNext())
System.out.print(pre.next().getVirtual_x() + "\t");
    
System.out.println();
System.out.println();
    
Iterator<Tree> preCC = root.PreOrder(false);
System.out.println("              \t");
while(preCC.hasNext())
    System.out.print(preCC.next() + "\t");
    
preCC = root.PreOrder(false);
System.out.println();
System.out.println("x-coordinates:\t");
while(preCC.hasNext())
System.out.print(preCC.next().getVirtual_y() + "\t");

Also here is a quote to better explain the x,y coordinates.
the vertices.the y-coordinates for the vertices.

Compute the counterclockwise
pre-ordering of the vertices of T (the
ordering are numbered from 0 to n −
1), use them as the x-coordinates for
the vertices.

Compute the clockwise pre-ordering of
the vertices of T (the ordering are
numbered from 0 to n − 1), use them as
the y-coordinates for the vertices.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

故事灯 2024-10-07 10:23:14

Java 总是按值传递——无论是原语还是对象。它是为非基元传递的引用,因此您可以更改它们指向的对象的状态,但不能更改引用本身。

来自 James Gosling 在《Java 编程语言》中:

"...只有一个参数
Java中的传递模式——按值传递——
这让事情变得简单。 ..”

我认为这是对此的最终决定权。

我意识到这对于 Java 程序员来说是一个备受争议、有争议的话题

。不,没有争议。 James Gosling 从一开始就将这一点融入到了语言中。如果你认为这是有争议的,那你可悲的是被欺骗了或无知了。

Java's pass by value, always - for both primitives and objects. It's references that are passed for non-primitives, so you can change the state of the objects they point to but not the references themselves.

From James Gosling in "The Java Programming Language":

"...There is exactly one parameter
passing mode in Java - pass by value -
and that keeps things simple. .."

I think that's the final authority on this.

I realize this is a hotly debated, controversial topic for Java programmers

No, there's no debate. This has been baked into the language since the beginning by James Gosling. If you think it's controversial, you're sadly deluded or ignorant.

呆头 2024-10-07 10:23:14

实际上,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);
}

像这样调用 swap:

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 思考。

actually, there is a way to pass by reference in Java:

class Pointer {
    private Object ptr;
    public Pointer(Object v)  { set(v);  }
    public void set(Object v) { ptr = v; }
    public Object get()       { return ptr; }
}

and you use them:

public void swap(Pointer a, Pointer b) {
    Object tmp = a.get();
    a.set(b.get());
    b.set(tmp);
}

and call swap like this:

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());
}

though, if you're really doing this, then you're probably either insane or just not thinking in Java yet.

吹梦到西洲 2024-10-07 10:23:14

您不需要通过引用传递,您需要一个具有副作用的函数。通过引用传递将是实现这一目标的一种方法;使用可变对象作为函数参数是另一种情况。

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);
    }
}

You don't require pass by reference, you require a function with side effects. Pass by reference would be one way to achieve this; using a mutable object as a function argument would be another.

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文