resueltos recorrido preorden por ordenamiento niveles matematicas ejercicios ejemplos discretas busqueda binarios binario arboles arbol algoritmo php html traversal nested-sets

php - por - Obtención de un modelo de recorrido de árbol de preorden modificado(conjunto anidado) en un<ul>



recorrido por niveles arbol binario c++ (7)

Estoy tratando de obtener mis datos que se configuran jerárquicamente con un modelo de recorrido de árbol en una <ul> para mostrarlos en mi sitio.

Aquí está mi código:

function getCats($) { // retrieve all children of $parent $query = "SELECT max(rght) as max from t_categories"; $row = C_DB::fetchSingleRow($query); $max = $row["max"]; $result ="<ul>"; $query = "SELECT * from t_categories where lft >=0 and rght <= $max"; if($rs = C_DB::fetchRecordset($query)){ $p_right =""; $p_left =""; $p_diff=""; while($row = C_DB::fetchRow($rs)){ $diff = $row["rght"] -$row["lft"]; if($diff == $p_diff){ $result.= "<li>".$row[''title'']."</li>"; }elseif (($row["rght"] - $row["lft"] > 1) && ($row["rght"] > $p_right)){ $result. "<ul>"; $result.= "<li>".$row[''title'']."</li>"; }else{ $result.= "<li>".$row[''title'']."</li>"; } $p_right = $row["rght"]; $p_left = $row["lft"]; $p_diff = $diff; } } $result.= "</ul>"; return $result; }

Aquí está mi tabla de muestra:

|ID | TITLE | lft| rght | |1 | Cat 1 | 1 | 16 | |18 | Cat 2 | 3 | 4 | |22 | Cat 3 | 5 | 6 | |28 | Cat 4 | 7 | 8 | |34 | Cat 5 | 9 | 9 | |46 | Cat 6 | 11 | 10 | |47 | Cat 7 | 13 | 12 | |49 | Cat 8 | 15 | 14 |

Ahora produce algo como:

<ul> <li>Cat 1</li> <li>Cat 2</li> <li>Cat 3</li> <li>Cat 4</li> <li>Cat 5</li> <li>Cat 6</li> <li>Cat 7</li> <li>Cat 8</li> </ul>

¿Puede alguien decirme por qué o cómo generará la lista en una estructura jerárquica?

Tema relacionado


Esto debería ser lo que estás buscando:

function getCats($left = null, $right = null) { $sql = array(); $result = null; if (isset($left) === true) { $sql[] = ''lft >= '' . intval($left); } if (isset($right) === true) { $sql[] = ''rght <= '' . intval($right); } if (empty($sql) === true) { $sql[] = ''lft = 1''; } $sql = ''SELECT * FROM t_categories WHERE '' . implode('' AND '', $sql) . '';''; if ($rs = C_DB::fetchRecordset($sql)) { // you need to make sure that the query returns // something to correctly display the ULs if (empty($rs) === false) { $result .= ''<ul>'' . "/n"; while ($row = C_DB::fetchRow($rs)) { $result .= ''<li>'' . $row[''title''] . ''</li>'' . "/n"; $result .= getCats($row[''lft''], $row[''rght'']); } $result .= ''</ul>'' . "/n"; } } return $result; }

Para obtener el HTML para su árbol anidado debe hacer:

echo getCats();

Tenga en cuenta que su ejemplo de conjunto anidado no se ve bien, también debe asegurarse de que si no cometí algún error al invocar su clase C_DB, no lo sé ya que no estoy familiarizado con él.


Estoy usando la consulta CROSS JOIN que muestra el menú jsTree jQuery; ¡Todo funciona simplemente genial! La tabla existente agregué una columna para la posición. Sin embargo, cuando defino la posición y ordeno todos por posición, los elementos correspondientes no se agrupan correctamente. Supongo que es un problema de consulta, probé muchas combinaciones, pero no tuve éxito.



Ok, vamos a hacer una caza de recompensas;)

Paso 0 - Ejemplo de desinfección:
Como ya se mencionó, sus datos de ejemplo están rotos, ya que no define un conjunto anidado válido. Si tomó estos datos de una aplicación, debería verificar la lógica de inserción / eliminación.

Así que para las pruebas, usé una versión desinfectada como la siguiente:
(MySQL aquí, ya que era la primera a la mano)

CREATE TABLE t_categories`( `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, `title` VARCHAR(45) NOT NULL, `lft` INTEGER UNSIGNED NOT NULL, `rght` INTEGER UNSIGNED NOT NULL, PRIMARY KEY (`id`) ); INSERT INTO t_categories (title, lft, rght) VALUES (''Cat 1'',1,16); INSERT INTO t_categories (title, lft, rght) VALUES (''Cat 2'',2,3); INSERT INTO t_categories (title, lft, rght) VALUES (''Cat 3'',4,7); INSERT INTO t_categories (title, lft, rght) VALUES (''Cat 4'',5,6); INSERT INTO t_categories (title, lft, rght) VALUES (''Cat 5'',8,13); INSERT INTO t_categories (title, lft, rght) VALUES (''Cat 6'',9,12); INSERT INTO t_categories (title, lft, rght) VALUES (''Cat 7'',10,11); INSERT INTO t_categories (title, lft, rght) VALUES (''Cat 8'',14,15);

Paso 1 - Deje que la base de datos haga el pedido.
Los conjuntos anidados se inventaron principalmente como una forma conveniente de almacenar árboles en bases de datos, ya que facilitan la búsqueda de subárboles, relaciones con los padres y, especialmente interesante en este caso, para el orden y la profundidad:

SELECT node.title, (COUNT(parent.title) - 1) AS depth FROM t_categories AS node CROSS JOIN t_categories AS parent WHERE node.lft BETWEEN parent.lft AND parent.rght GROUP BY node.title ORDER BY node.lft

Esto devolverá su conjunto ordenado cuidadosamente, comenzando con el nodo raíz y continuando hasta el final en la pre-compra. Lo más importante es que agregará la profundidad de cada nodo como un entero positivo, indicando cuántos niveles el nodo está debajo de la raíz (nivel 0). Para los datos de ejemplo anteriores, el resultado será:

title, depth ''Cat 1'', 0 ''Cat 2'', 1 ''Cat 3'', 1 ''Cat 4'', 2 ''Cat 5'', 1 ''Cat 6'', 2 ''Cat 7'', 3 ''Cat 8'', 1

En codigo:

// Grab ordered data $query = ''''; $query .= ''SELECT node.title, (COUNT(parent.title) - 1) AS depth''; $query .= '' FROM t_categories AS node''; $query .= '' CROSS JOIN t_categories AS parent''; $query .= '' WHERE node.lft BETWEEN parent.lft AND parent.rght''; $query .= '' GROUP BY node.title''; $query .= '' ORDER BY node.lft''; $result = mysql_query($query); // Build array $tree = array(); while ($row = mysql_fetch_assoc($result)) { $tree[] = $row; }

La matriz resultante se verá así:

Array ( [0] => Array ( [title] => Cat 1 [depth] => 0 ) [1] => Array ( [title] => Cat 2 [depth] => 1 ) ... )

Paso 2 - Salida como fragmento de la lista HTML:

Usando while loop:

// bootstrap loop $result = ''''; $currDepth = -1; // -1 to get the outer <ul> while (!empty($tree)) { $currNode = array_shift($tree); // Level down? if ($currNode[''depth''] > $currDepth) { // Yes, open <ul> $result .= ''<ul>''; } // Level up? if ($currNode[''depth''] < $currDepth) { // Yes, close n open <ul> $result .= str_repeat(''</ul>'', $currDepth - $currNode[''depth'']); } // Always add node $result .= ''<li>'' . $currNode[''title''] . ''</li>''; // Adjust current depth $currDepth = $currNode[''depth'']; // Are we finished? if (empty($tree)) { // Yes, close n open <ul> $result .= str_repeat(''</ul>'', $currDepth + 1); } } print $result;

Misma lógica que la función recursiva:

function renderTree($tree, $currDepth = -1) { $currNode = array_shift($tree); $result = ''''; // Going down? if ($currNode[''depth''] > $currDepth) { // Yes, prepend <ul> $result .= ''<ul>''; } // Going up? if ($currNode[''depth''] < $currDepth) { // Yes, close n open <ul> $result .= str_repeat(''</ul>'', $currDepth - $currNode[''depth'']); } // Always add the node $result .= ''<li>'' . $currNode[''title''] . ''</li>''; // Anything left? if (!empty($tree)) { // Yes, recurse $result .= renderTree($tree, $currNode[''depth'']); } else { // No, close remaining <ul> $result .= str_repeat(''</ul>'', $currNode[''depth''] + 1); } return $result; } print renderTree($tree);

Ambos darán salida a la siguiente estructura:

<ul> <li>Cat 1</li> <li> <ul> <li>Cat 2</li> <li>Cat 3</li> <li> <ul> <li>Cat 4</li> </ul> </li> <li>Cat 5</li> <li> <ul> <li>Cat 6</li> <li> <ul> <li>Cat 7</li> </ul> </li> </ul> </li> <li>Cat 8</li> </ul> </li> </ul>

Nitpickers corner: Questioner preguntó explícitamente por <ul> , pero ¿ ordenó listas desordenadas? Venga...
;-)


Simplemente haga un bucle a través del resultado que hará:

$sql = "SELECT node.name, (COUNT(parent.name) - 1) AS depth FROM nested_category AS node, nested_category AS parent WHERE node.lft BETWEEN parent.lft AND parent.rgt GROUP BY node.name ORDER BY node.lft"; $query_result = mysql_query($sql) $result = "<ul>"; $currDepth = 0; while($row = mysql_fetch_assoc($query_result)) { if($row[''depth''] > $currDepth) { $result .= "<li><ul>"; // open sub tree if level up } if($row[''depth''] < $currDepth) { $result .= str_repeat("</ul></li>", $currDepth - $row[''depth'']); // close sub tree if level down } $result .= "<li>$row[''name'']</li>"; // Always add node $currDepth = $row[''depth'']; } $result .= "</ul>"; echo $result;


Mejor función de árbol de renderización que funcionó para mí ( función php para preparar la fuente html para su uso en el complemento jsuerte jQuery ) en lugar del de Henrik Opel:

function MyRenderTree ( $tree = array(array(''name''=>'''',''depth''=>'''')) ){ $current_depth = 0; $counter = 0; $result = ''<ul>''; foreach($tree as $node){ $node_depth = $node[''depth'']; $node_name = $node[''name'']; $node_id = $node[''category_id'']; if($node_depth == $current_depth){ if($counter > 0) $result .= ''</li>''; } elseif($node_depth > $current_depth){ $result .= ''<ul>''; $current_depth = $current_depth + ($node_depth - $current_depth); } elseif($node_depth < $current_depth){ $result .= str_repeat(''</li></ul>'',$current_depth - $node_depth).''</li>''; $current_depth = $current_depth - ($current_depth - $node_depth); } $result .= ''<li id="c''.$node_id.''"''; $result .= $node_depth < 2 ?'' class="open"'':''''; $result .= ''><a href="#"><ins>&nbsp;</ins>''.$node_name.''</a>''; ++$counter; } $result .= str_repeat(''</li></ul>'',$node_depth).''</li>''; $result .= ''</ul>''; return $result;}

Resultado HTML:

<ul> <li id="c1" class="open"><a href="#"><ins>&nbsp;</ins>ELECTRONICS</a> <ul> <li id="c2" class="open"><a href="#"><ins>&nbsp;</ins>TELEVISIONS</a> <ul> <li id="c3"><a href="#"><ins>&nbsp;</ins>TUBE</a></li> <li id="c4"><a href="#"><ins>&nbsp;</ins>LCD</a></li> <li id="c5"><a href="#"><ins>&nbsp;</ins>PLASMA</a> <ul> <li id="c14"><a href="#"><ins>&nbsp;</ins>PLASMA1</a></li> <li id="c15"><a href="#"><ins>&nbsp;</ins>PLASMA2</a></li> </ul> </li> </ul> </li> <li id="c6" class="open"><a href="#"><ins>&nbsp;</ins>PORTABLE ELECTRONICS</a> <ul> <li id="c7"><a href="#"><ins>&nbsp;</ins>MP3 PLAYERS</a> <ul> <li id="c8"><a href="#"><ins>&nbsp;</ins>FLASH</a></li> </ul> </li> <li id="c9"><a href="#"><ins>&nbsp;</ins>CD PLAYERS</a></li> <li id="c10"><a href="#"><ins>&nbsp;</ins>2 WAY RADIOS</a></li> </ul> </li> </ul> </li> </ul>


$linaje=''''; $lastnode=''''; $sides[''izq'']=array(); $sides[''der'']=array(); $print = ''<ul>''; foreach ($array as $key1 => $value1){ //Proyectos if(strpos($info[$key1][''linaje''],''-'') !== false) $compare = strstr($info[$key1][''linaje''],''-'',true); else $compare = $info[$key1][''linaje'']; if($linaje != ''''){ if ($linaje != $compare){ $linaje= $compare; $sides[''izq'']=array(); $sides[''der'']=array(); //for($i=1;$i <= substr_count($lastnode,''`'')-substr_count($value1,''`'');$i++) //$print .= ''</ul></li>''; } } if ($lastnode != '''') for($i=1;$i<= substr_count($lastnode,''`'')-substr_count($value1,''`'');$i++) $print .= ''</ul></li>''; if (count($sides[''der''])>0) if ($sides[''der''][count($sides[''der''])-1] > $info[$key1][''der'']) $print .= ''<ul>''; $print .= ''<li><a href="#''.$info[$key1][''id''].''#''.$info[$key1][''linaje''].''">''.substr($value1,substr_count($value1,''`'')).''</a>''; if ($info[$key1][''der''] - $info[$key1][''izq''] == 1) $print .= ''</li>''; if ($key1 == count($info)-1) for($i=1;$i <= substr_count($lastnode,''`'')-1;$i++) $print .= ''</ul></li>''; $sides[''der''][] = $info[$key1][''der'']; $sides[''izq''][] = $info[$key1][''izq'']; if ($linaje =='''') $linaje = $info[$key1][''linaje'']; $lastnode = $value1; } $print .= ''</ul>''; echo $print;

La diferencia en esto es que puedes representar X números de árboles, esto se aplica a uno de mis proyectos. y uso un char como referencia de profundidad cuando recupero las filas de la base de datos