PHP树结构的应用,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。有了这样的表我们就可以通过数据库保存整个多级树状结构了。

显示多级树

如果我们需要显示这样的一个多级结构需要一个递归函数。

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"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值