|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
我假设你目前已经可以完成一个静态页面了,当然,做的好看难看是另外一说,皮皮我的第一个网页也没好看到哪去,但是“孩子”再丑,咱们做“爹妈”的也不能嫌弃不是?这毕竟是咱的成果。 从喜悦村上转载,之前也读过此文,讲述得仍是对照清晰的。
产物分类,多级的树状布局的服装论坛,邮件列表等很多中央咱们城市碰到如许的成绩:若何存储多级布局的数据?
在PHP的使用中,供应后台数据存储的凡是是关系型数据库,它可以保留大批的数据,供应高效的数据检索和更新办事。但是关系型数据的根基模式是犬牙交错的表,是一个立体的布局,假如要将多级树状布局存储在关系型数据库里就需求停止公道的翻译任务。接上去我会将本人的所见所闻和一些适用的经历和人人切磋一下。
层级布局的数据保留在立体的数据库中根基上有两种经常使用设计办法:
毗连目次形式(adjacency list model)
预排序遍历树算法(modified preorder tree traversal algorithm)
我不是盘算机专业的,也没有学过甚么数据布局的器材,所以这两个名字都是我本人依照字面的意思翻的,假如说错了还请多多指教。
这两个器材听着仿佛很吓人,其实十分轻易了解。这里我用一个复杂食物目次作为咱们的示例数据。 咱们的数据布局是如许的:
Food
|
|---Fruit
| |
| |---Red
| | |
| | |--Cherry
| |
| |---Yellow
| |
| |--Banana
|
|---Meat
|
|--Beef
|
|--Pork
为了照料那些英文乌烟瘴气的PHP喜好者
Food:食品
Fruit:生果
Red:白色
Cherry:樱桃
Yellow:黄色
Banana:喷鼻蕉
Meat:肉类
Beef:牛肉
Pork:猪肉
毗连目次形式(adjacency list model)
这类形式咱们常常用到,良多的教程和书中也引见过。咱们经由过程给每一个节点增添一个属性 parent 来暗示这个节点的父节点从而将全部树状布局经由过程立体的表描写出来。依据这个准绳,例子中的数据可以转化成以下的表:
+-----------------------+
| parent | name |
+-----------------------+
| | Food |
| Food | Fruit |
| Fruit | Green |
| Green | Pear |
| Fruit | Red |
| Red | Cherry |
| Fruit | Yellow |
| Yellow | Banana |
| Food | Meat |
| Meat | Beef |
| Meat | Pork |
+-----------------------+
咱们看到 Pear 是Green的一个子节点,Green是Fruit的一个子节点。而根节点'Food'没有父节点。 为了复杂地描写这个成绩, 这个例子中只用了name来暗示一个纪录。 在实践的数据库中,你需求用数字的id来标示每一个节点,数据库的表布局也许应当像如许:id, parent_id, name, description。有了如许的表咱们就能够经由过程数据库保留全部多级树状布局了。
显示多级树
假如咱们需求显示如许的一个多级布局需求一个递归函数。
<?php
// $parent is the parent of the children we want to see
// $level is increased when we go deeper into the tree,
// used to display a nice indented tree
function display_children($parent, $level)
{
// 取得一个 父节点 $parent 的一切子节点
$result = mysql_query('SELECT name FROM tree '.
'WHERE parent="'.$parent.'";');
// 显示每一个子节点
while ($row = mysql_fetch_array($result))
{
// 缩进显示节点称号
echo str_repeat(' ',$level).$row['name']."n";
//再次挪用这个函数显示子节点的子节点
display_children($row['name'], $level+1);
}
}
?>
对全部布局的根节点(Food)利用这个函数就能够打印出全部多级树布局,因为Food是根节点它的父节点是空的,所以如许挪用: display_children('',0)。将显示全部树的内容:
Food
Fruit
Red
Cherry
Yellow
Banana
Meat
Beef
Pork
假如你只想显示全部布局中的一局部,好比说生果局部,就能够如许挪用:
display_children('Fruit',0);
几近利用一样的办法咱们可以晓得从根节点就任意节点的途径。好比 Cherry 的途径是 "Food > Fruit > Red"。 为了失掉如许的一个途径咱们需求从最深的一级"Cherry"入手下手, 查询失掉它的父节点"Red"把它添加到途径中, 然后咱们再查询Red的父节点并把它也添加到途径中,以此类推直到最高层的"Food"
<?php
// $node 是谁人最深的节点
function get_path($node)
{
// 查询这个节点的父节点
$result = mysql_query('SELECT parent FROM tree '.
'WHERE name="'.$node.'";');
$row = mysql_fetch_array($result);
// 用一个数组保留途径
$path = array();
// 假如不是根节点则持续向上查询
// (根节点没有父节点)
if ($row['parent']!='')
{
// the last part of the path to $node, is the name
// of the parent of $node
$path[] = $row['parent'];
// we should add the path to the parent of this node
// to the path
$path = array_merge(get_path($row['parent']), $path);
}
// return the path
return $path;
}
?>
假如对"Cherry"利用这个函数:print_r(get_path('Cherry')),就会失掉如许的一个数组了:
Array
(
[0] => Food
[1] => Fruit
[2] => Red
)
接上去若何把它打印成你但愿的格局,就是你的工作了。
弱点:这类办法很复杂,轻易了解,好上手。然而也有一些弱点。次要是由于运转速度很慢,因为失掉每一个节点都需求停止数据库查询,数据量大的时分要停止良多查询才干完成一个树。别的因为要停止递归运算,递归的每级都需求占用一些内存所以在空间使用上效力也对照低。
如今让咱们看一看别的一种不利用递归盘算,加倍疾速的办法,这就是预排序遍历树算法(modified preorder tree traversal algorithm) 这类办法人人能够接触的对照少,初度利用也不像下面的办法轻易了解,然而因为这类办法不利用递归查询算法,有更高的查询效力。
咱们起首将多级数据依照上面的体例画在纸上,在根节点Food的左边写上 1 然后沿着这个树持续向下 在 Fruit 的左边写上 2 然后持续行进,沿着全部树的边沿给每个节点都标上左边和右边的数字。最初一个数字是标在Food 右边的 18。 鄙人面的这张图中你可以看到全部标好了数字的多级布局。(没有看懂?用你的手指指着数字从1数到18就分明怎样回事了。还不分明,再数一遍,注重要挪动你的手指)。
这些数字标了然各个节点之间的关系,"Red"的号是3和6,它是 "Food" 1-18 的子孙节点。 一样,咱们可以看到 一切左值大于2和右值小于11的节点 都是"Fruit" 2-11 的子孙节点
一下弹出N多页面!很明显,你的留言本并没有做好安全防范,被人用JS代码小小的耍了一下,我很同情你这个时候的感受,但是没有别的办法了,继续努力吧! |
|