И вновь про деревья...

alex234

Guest
И вновь про деревья...

Ситуция: делаю дерево с Mysql (одной таблицей):

таблица: ID, PID, <данные>;

Если PID никуда не ссылается(0) - это корень дерева, иначе PID ссылается на своего родителя.

Код для обработки таблицы следующий:
PHP:
$connection=mysql_connect("127.0.0.1", "admin", "111");
mysql_select_db("content");

function rekurs($new1, $id, $uroven)
{
	while($new3=mysql_fetch_array($new1))
	{
		if($id==$new3[pid]):

			$i=0;
			while($i<$uroven){
			print("-");
			$i++;
			}
			print("$new3[id]<br>");

			rekurs($new1, $new3[id], $uroven+1);
		endif;
	}

}

$new1=mysql_query("select * from derevo_test");
rekurs($new1, 0, 0);
Неполадки: в результате рисуется не все дерево, а только одна ветка(до конца). Где ошибка?:confused:
 

alex234

Guest
ткни мне на это пальцем (ссылкой) есле тебе не очень сложно
pls
 

chira

Новичок
PHP:
function rekurs($id, $uroven) 
{ 
   $res=mysql_query("select * from derevo_test where pid='$id'"); 
   $nrows = mysql_num_rows($res);
   if($nrows > 0){
     while($new3=mysql_fetch_array($res))  { 
         for ($n = 0; $n < $uroven; $n++) echo '--';
         print("$new3[id]<br>"); 
         rekurs($new3[id], $uroven+1); 
     } 
   }
} 
rekurs(0, 0);
 

Crazy

Developer
Если мы строим ВСЕ дерево, то не будет ли проще сделать это одним SQL-запросом?
 

.des.

Поставил пиво кому надо ;-)
Crazy разве при такой структуре базы это возможно?
Если я не ошибаюсь то нет.
 

Crazy

Developer
Гы. "select * from derevo_test order by pid, id"

И уже в PHP построчно читаешь и строишь дерево. :)
 

shingrus

Guest
Автор оригинала: Crazy
Гы. "select * from derevo_test order by pid, id"

И уже в PHP построчно читаешь и строишь дерево. :)
Это ж просто гениально....:D как это мы и не придумали...
 

.des.

Поставил пиво кому надо ;-)
А понятно :)))
Гы. "select * from derevo_test order by pid, id"
И уже в PHP построчно читаешь и строишь дерево.
Где то я это уже видел - UltraTree поделка одного из участников этого форума.
Только я немного не об этом.. мне в этом не нравится часть фразы "И СТРОИШЬ" то есть все равно придется рекурсивно строить дерево в самом пхп. А средствами мускла я имел ввиду достать чтобы больше ничего не строить :)
Вот это как раз и невозможно при данной организации таблицы.
 

Crazy

Developer
Автор оригинала: Barlone
Crazy: А полностью код можно ?:D
Разумеется.

PHP:
<?php

// Из объектов класса Node будем строить узлы дерева.
class Node {

  var $id;
  var $items;

  function Node($id) {
    $this->id = $id;
    $this->items = array();
  }

  function add(&$child) {
    $this->items[$child->id] =& $child;
  }
}

// Созадем новый узел с указанным ID, имеющий указанного предка
function newNode($id,$parentID) {
  global $tree, $directAccess;
  $node = new Node($id);
  $directAccess[$id] =& $node;
  $parent =& $directAccess[$parentID];
  $parent->add($node);
}

// Инициализация структур данных
$tree = new Node(0);
$directAccess = array();
$directAccess[0] = &$tree;

// Подключаемся к базе
mysql_connect("localhost");
mysql_select_db("test");
// Вытаскиваем все дерево
$res = mysql_query("select id,pid from tree order by pid,id");
// Построчно читаем дерево и восстанавливаем структуру
while ($row = mysql_fetch_array($res)) {
  $id = (int)$row["id"];
  $parentID = (int)$row["pid"];
  newNode($id,$parentID);
}

// Вывод структуры дерева
function dump($tree) {
  echo "<ul>".$tree->id;
  foreach($tree->items as $index => $node)  {
    dump($node);
  }
  echo "</ul>";
}

dump($tree);

?>
Если при построении дерева использовать рекурсию, то код будет короче. Но так он более нагляден.
 

Crazy

Developer
Автор оригинала: .des.
Только я немного не об этом.. мне в этом не нравится часть фразы "И СТРОИШЬ" то есть все равно придется рекурсивно строить дерево в самом пхп.
Строить все равно придется -- как бы не были устроены данные. Тебе mysql_result все равно ДЕРЕВО не вернет, он вернет в любом случае плоский список строк. Просто структура этого списка может быть более или менее удобной для построения дерева.

Что до рекурсии -- нетрудно видеть, что приведенный выше алгоритм нерекурсивен.

Кстати, нюанс: в алгоритме используется тот факт, что pid>id для любого узла. Если это не так, то можно использовать двухпроходный алгоритм.
 

.des.

Поставил пиво кому надо ;-)
Тебе mysql_result все равно ДЕРЕВО не вернет, он вернет в любом случае плоский список строк
Согласен но это все равно удобнее :)
Что до рекурсии -- нетрудно видеть, что приведенный выше алгоритм нерекурсивен.
Любую рекурсию можно заменить нерекурсивным алгоритмом. В данном случае мы ничего от этого не потеряли и я соглашаюсь с тобой.

Я весь сегодня согласительный :)
 

.des.

Поставил пиво кому надо ;-)
Тебе mysql_result все равно ДЕРЕВО не вернет, он вернет в любом случае плоский список строк
Согласен но это все равно удобнее
Немножко поправлюсь. Если задача - просто вывод дерева(или ветки) то мне больше ничего и не нужно от result seta.
 
Сверху