views:

142

answers:

3

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.

+9  A: 

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.

duffymo
Ok, I understand this, but how does this help me solve my problem? The reason for asking this question was not to spark a debate, but move towards a solution to the problem I presented.
Nathan
Sadly enough there *is* debate - uninformed on one side, of course. Some random chap emailed me about this just last night, trying to convince me that Java always uses pass by reference :(
Jon Skeet
It's like creationism versus evolution for me: both sides aren't equal in weight.
duffymo
@Nathan - Sorry, the way you worded your question makes it sound like you not only think that Java is pass by reference, but that it's the solution to your problem. If you don't believe that, I'd edit your wording. I'd also make your problem clearer, because tree traversal by recursion is commonly done in Java. Maybe there's something else that you're missing.
duffymo
@Jon: I don't care about getting involved the debate. I need to know whether I should change my algorithm or my code.
Nathan
Can't really tell what you want to do - can you make it clearer? I get the tree traversal. What are those rows you're printing out supposed to be for? Tell us in words rather than code.
duffymo
See the note below the output. I am printing out the order the nodes are visited in then coordinates (aka count) I am assigning to the respective node.
Nathan
*"It's like creationism versus evolution for me: both sides aren't equal in weight."* - The flat earth "debate" is a better analogy, IMO.
Stephen C
I think they're about on par.
duffymo
@duffymo - possibly. But think about the relative ease of dismissing the creationism and flat earth arguments.
Stephen C
@Nathan from your question, it is very unclear what you mean by x- and y-coordinates when it comes to tree traversal.
matt b
@matt: see edit
Nathan
A: 

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.

Lie Ryan
Just to be clear, that's not *actually* doing pass by reference. It's *simulating* pass by reference via an extra level of indirection. I'm not saying it doesn't work, just that it's not like it's making the language change its passing scheme :)
Jon Skeet
This is not passing by reference - sorry.
duffymo
@duffymo: yes, it's not passing by reference, it's more similar to pass-by-pointer. If you replace all `a.get()` with `*a` and `a.set(...)` with `*a = ...`, you'll get the more familiar pass-by-pointer from C/C++. pointer is generally agreed to be a specific form of reference, therefore pass-by-pointer is a specific type of pass-by-reference (though some purists may disagree, since the pointer itself is still passed by value).
Lie Ryan
@duffymo: also, you need a little sense of humor ;)
Lie Ryan
When I see something humorous, I'll laugh. If you're expressing your wry side with this code Lie Ryan, I'm afraid that SO, the Internet, and the browser are filtering it out.
duffymo
Lie Ryan, you don't sound like a person who's looking for belly laughs when you persist with your "pass-by-pointer" argument. You sound more like another person who doesn't really understand how it works. What you're saying is only confusing the issue. Sorry if that sounds stern and un-jolly to you, but that's the truth. Keep repeating "Java is pass by value, all the time" and you'll get it eventually.
duffymo
@duffymo: precisely, you have no sense of humour; and no, I'm not looking for belly laughs, a humor that is easy to understand is not funny enough.
Lie Ryan
Excellent, Lie Ryan. I'll keep watching for your punchlines.
duffymo
"Java is pass by value, all the time" is technically correct, though things do get a bit complicated with JNI and longs that represent pointers to native objects.
alpha123
@alpha123 - no they don't. Unless the JNI can alter the value of a `long` variable in the caller, it ain't call by reference.
Stephen C
I know it ain't call by reference (it never is), though it's sort of call by pointer with JNI. Sort of because the pointer isn't to a Java object.
alpha123
A: 

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