php:树形结构的简便算法1

    作者:课课家更新于: 2015-11-06 10:47:11

    大神带你学编程,欢迎选课

     

    获得知识的途径有很多,现在由小编为大家讲解有关语言编程的文章希望对大家有所帮助


     c语言编程入门 产品分类,多级的树状结构的论坛,邮件列表等许多地方我们都会遇到这样的问题:如何存储多级结构的数据?
      
      在的应用中,提供后台数据存储的通常是关系型,它能够保存大量的数据,提供高效的数据检索和更新服务。然而关系型数据的基本形式是纵横交错的表,是一个平面的结构,如果要将多级树状结构存储在关系型数据库里就需要进行合理的翻译工作。接下来我会将自己的所见所闻和一些实用的经验和大家探讨一下。
      
      层级结构的数据保存在平面的数据库中基本上有两种常用方法:
      
      毗邻目录模式(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:猪肉


       "IOBE 编程语言社区排行榜是编程语言流行趋势的一个指标,每月更新,这份排行榜排名基于互联网上有经验的程序员、课程和第三方厂商的数量。排名使用著名的搜索引擎(诸如 Google、MSN、Yahoo!、Wikipedia、YouTube 以及 Baidu 等)进行计算。请注意这个排行榜只是反映某个编程语言的热门程度,并不能说明一门编程语言好不好,或者一门语言所编写的代码数量多少。 教育资源可能会影响结果。例如Python是常用的学校和学习编程途径,成千上万的学生问问题和完成项目。不过根据我的经验来说,Python的工作相比PHP和Ruby来说是罕见的。Java也有类似的情况,因为它在教育、网络、桌面和移动发展上有各种各样的用途,所以它们的排名会相对靠前。
    本地开发者的需求仍然很高,尤其是在相关工作的调查中可以看出。RedMonk报告Swift在不到六个月的时间里上升了46个排名达到第22位。然而应用开发是一门年轻的学科。目前有更多的Web和桌面编程职位空缺着。 "

      毗邻目录模式(adjacency list model)
      
      C语言视频教程这种模式我们经常用到,很多的教程和书中也介绍过。我们通过给每个节点增加一个属性 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。有了这样的表我们就可以通过数据库保存整个多级树状结构了。
      
      显示多级树
      如果我们需要显示这样的一个多级结构需要一个递归函数。
      
      

      // $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 =_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);
      
      c语言程序设计几乎使用同样的方法我们可以知道从根节点到任意节点的路径。比如 Cherry 的路径是 "Food > Fruit > Red"。 为了得到这样的一个路径我们需要从最深的一级"Cherry"开始, 查询得到它的父节点"Red"把它添加到路径中, 然后我们再查询Red的父节点并把它也添加到路径中,以此类推直到最高层的"Food"
      
      

      // $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 的子孙节点

    文章很精彩,是否还想了解更多关于视频教程的文章,课课家官网是一个知识的海洋

课课家教育

未登录