Page 1 of 2

recursion

Posted: Sat Dec 30, 2006 6:06 am
by arukomp
Hello,

I'm using recursion method to show tree. Now i need to look at that tree and find the nearest node which has less than 3 children nodes and return that node.

Here's the code i created so far:

Code: Select all

function findref2($refid){
	$result = mysql_query("SELECT id FROM users WHERE refid='$refid'");
	if (mysql_num_rows($result) < 3) {
		return $refid;
		exit;
	}
	elseif (mysql_num_rows($result) >= 3) {
		while($row = mysql_fetch_array($result)){
		 	findref2($row['id']);
		} // while
	}
}

$ref2 = findref2(2);
Everything works good until the first node has less than 3 children. When elseif is chosen, the function doesn't return anything, so in MySQL database refid is saved as 0.

Can anyone help me with this problem? Why it doesn't return anything if there are more instances of this function?

Thanks for answers

Posted: Sat Dec 30, 2006 6:29 am
by volka
elseif (mysql_num_rows($result) >= 3) {
while($row = mysql_fetch_array($result)){
findref2($row['id']);
} // while
}
There's no return statement in this block.

Posted: Sat Dec 30, 2006 6:50 am
by arukomp
Yeah, but there's in the first block. In the second block it calls the function itself with different refid, so there are more instances of function, but only one of them will execute the first if statement, which should return a recent used refid

Posted: Sat Dec 30, 2006 6:52 am
by timvw
Who cares about what happens in the first block if you're in the second block? If you want all code paths to return something you'll need a return statement there too...

Posted: Sat Dec 30, 2006 7:06 am
by arukomp
yeah, but this function keeps running until it executes the first if statement, which returns a value and exits.

Posted: Sat Dec 30, 2006 7:13 am
by timvw
But the 'returning' is only done to calling level.. It's not moved up in the call chain

eg:

Code: Select all

function foo() {
 return 5;
}

function bar() {
  foo();
}
bar returns void.. where you seem to think that it would return 5.

Posted: Sat Dec 30, 2006 7:18 am
by arukomp
timvw wrote:But the 'returning' is only done to calling level.. It's not moved up in the call chain

eg:

Code: Select all

function foo() {
 return 5;
}

function bar() {
  foo();
}
bar returns void.. where you seem to think that it would return 5.
well, yeah :)

any suggestions how can i fix it?

Posted: Sat Dec 30, 2006 7:23 am
by volka

Code: Select all

if (mysql_num_rows($result) < 3) {
	return $refid;
}
elseif (mysql_num_rows($result) >= 3) {
 // what is the function supposed to return in this case?
}
Just explain it in your own words, without code, but think a while about it.

Posted: Sat Dec 30, 2006 7:38 am
by arukomp
ok, starting over.

The function i want to create is supposed to control spillover. The script is a forced matrix, 3x9, so there can't be more than 3 members under the first level of each person.

Lets say that new user has joined. His sponsor already has 3 members under his 1st level, so we need to find the nearest member in sponsor's downline, which doesn't have 3 members under his 1st level. Then we need to return that member's id and insert the new user's data and place him under that member.

This is what i want to do. I told this, because maybe there's another and better way to do this.

Posted: Sat Dec 30, 2006 7:53 am
by feyd
It would seem that a hierarchical structure may be more useful as it's simple math to engineer the result set you want.

http://www.sitepoint.com/print/1105

Posted: Sat Dec 30, 2006 7:58 am
by arukomp
feyd wrote:It would seem that a hierarchical structure may be more useful as it's simple math to engineer the result set you want.

http://www.sitepoint.com/print/1105
I've read it all a day ago. I've chosen the first method to keep work hierarchical data. But i don't know how to find the nearest node, which has less than 3 children.

Again...

The function i want to create is supposed to control spillover. The script is a forced matrix, 3x9, so there can't be more than 3 members under the first level of each person.

Lets say that new user has joined. His sponsor already has 3 members under his 1st level, so we need to find the nearest member in sponsor's downline, which doesn't have 3 members under his 1st level. Then we need to return that member's id and insert the new user's data and place him under that member.

This is what i want to do. I told this, because maybe there's another and better way to do this.

Posted: Sat Dec 30, 2006 3:09 pm
by arukomp
No one knows? :(

Posted: Sat Dec 30, 2006 3:23 pm
by volka
arukomp wrote:ok, starting over.
Why? Couldn't you just try to answer only the specific question instead of describing the whole function+purpose?

Posted: Sat Dec 30, 2006 3:32 pm
by arukomp
volka wrote:

Code: Select all

if (mysql_num_rows($result) < 3) {
	return $refid;
}
elseif (mysql_num_rows($result) >= 3) {
 // what is the function supposed to return in this case?
}
Just explain it in your own words, without code, but think a while about it.
In this case, the function shouldn't return anything. It should start the function again with another $refid value. It should keep doing that until one instance of the function executes the first if statement. Then it returns $refid value, which was used in that function.

Posted: Sat Dec 30, 2006 4:01 pm
by volka
Ok, you still haven't understood how functions and return work.
If the function does not return anything in this case ...it does not return anything, nada, njiente. It does not matter wether a function calls itself or another function. If the function calls itself it's still a function call.
There's something called call stack. You can put a new item on the stack and you can remove the topmost item. But if you want to remove an item below other items you first have to remove all the items above. That's how function calls work. e.g.

Code: Select all

function foo() {
	return 3;
}

function bar() {
	$v = foo();
	echo 'v: ', $v, "<br />\n";
}

$v = bar();
echo 'v: ', $v, "<br />\n";
when the script's execution reaches the line return 3; the call stack looks like
foo <- bar <- [main]
foo is still executed. When it's done the script continues with the code in bar() after the call of foo(). When bar() is done [main] continues after the call of bar().
A return value is only available to next topmost item on the call stack. So foo() can only return a value to bar(). If bar() doesn't pass that value to [main] it's lost.
The same is true if bar() calls itself.

Code: Select all

function bar($param) {
	if ( 0==$param) {
		return 'xyz';
	}
	else {
		bar($param-1);
	}
}

$v = bar(1);
echo $v;
When bar() is called the first time ( bar(1) ) the call stack is bar<-[main]. Let's add the parameters to the call stack: bar(1)<-[main]
$param is not 0, therefore the else-block is executed and bar calls itself, this time with the parameter 1-1=0, call stack: bar(0)<-bar(1)<-[main]
Questions: whereto does return 'xyz'; return the string? What happens next?