【问题标题】:php recursive function for genealogical tree家谱树的php递归函数
【发布时间】:2018-10-30 10:28:48
【问题描述】:

我在数据库中有与父母有关的人,我需要创建递归函数,该函数返回带有家谱树的数组。数据库示例:

NUMBER;NAME;FATHER;MOTHER
001;Name1;002;005
002;Name2;007;018
003;Name3;018;025
005;Name5;006;019
023;Name23;019;045
018;Name18;062;097
007;Name7;;-
...

我准备了两个函数 - 第一个用于 man 详细信息,第二个用于搜索祖先的递归。

我需要这个结果:

$out[0][0] // first person
$out[1][0] // mother of first person
$out[1][1] // father of first person
$out[2][0] // grandmother of first person (mother side)
$out[2][1] // grandfather of first person (mother side)
$out[2][2] // grandmother of first person (father side)
$out[2][3] // grandmother of first person (father side)
...

下一代有 8 个项目,接下来的 16 个项目,...最多是 6 代。

我准备了两个函数——第一个用于人的详细信息,第二个用于树构建的递归。在第二个函数中

define("MAX_GEN",5);

function detail($number) {
    $d = mysql_query("select * from table where number = '$number'");
    if(mysql_num_rows($d) == 0) {
        $p[name] = "N/A";
        $p[number] = "N/A";
        $p[m_number] = "N/A";
        $p[f_number] = "N/A";
    }
    else $p = mysql_fetch_assoc($d);
    return $p;
}

function gen($number, $generation = 0, $out) {

    if ($generation >= MAX_GEN) {
        return false;
    }

    $record = detail($number);

    if ($generation == 0) $out[0][] = $record; // first man

    $generation++; // next generation

    if (!$out[$generation] && ($generation != MAX_GEN)) $out[$generation] = array();

    $x_mother = gen($record[m_number], $generation ); // continue with mother
    $x_father = gen($record[f_number], $generation ); // continue with father

    if ($out[$generation]) {
        $out[$generation][] = $x_mother;
        $out[$generation][] = $x_father;
    }
    return $out;
}

但在第二个函数中存在问题 - 我不知道如何将带有结果的数组传递给下一代和下一代。它仍然返回一个元素,或者(经过几次尝试)它返回我想要的数组,但是在代之间插入了数组,结果不可用。谁能帮帮我?

我想要的结果示例在这里:http://www.foxterrier.cz/_TM_importy/example.php

【问题讨论】:

  • 为什么要使用早已弃用的mysql_ 代码库?它在多年前就停产了,并在 PHP7 中完全删除。不应使用此库编写新代码。它使您容易受到 SQL 注入攻击(由于缺乏参数化查询支持)和潜在的其他未修补漏洞。尽快切换到使用mysqliPDO,然后学习如何编写参数化查询以保护您的数据免受恶意输入。请参阅bobby-tables.com 以获得对风险的简单说明以及一些用于安全编写查询的示例 PHP 代码。
  • 无论如何,您的示例代码有点不完整-请向我们展示您最初是如何调用“gen”方法的。并且还向我们展示了它目前产生的结果。谢谢。
  • 使用旧的不推荐使用的功能 - 我继承了旧网页(旧主机和 php 5.6),现在正在准备新版本。现在我只测试生成家谱树的可能性,所以我使用它们的旧功能。新网站将使用 mysqli
  • 好吧,这是一个合理的解释。现在更重要的是,您能否解决我的第二条评论,以便我们尝试修复您的算法?谢谢。
  • 感谢您的回复。我在数据库示例和结果中添加了几行,我尝试制作 link

标签: php arrays recursion parent genealogy


【解决方案1】:

这主要是评论 - 但有点长。

您受到数据库设计和所需输出格式的极大限制。即使不考虑a graph database 的成本/复杂性,representing hierarchical data in a relational database 也有很多方法。

您的输出格式列出了每一代,但不保持母父关联,并且不适合横向或向前映射 - 只能向后映射。

您的实现要求您运行 2^N(其中 N 是代数)查询,每次都从 PHP 代码到 DBMS 进行一次往返。性能会很糟糕。

至少您应该考虑一次解决一代:

  $ref=mysql_real_escape_string(session_id());
  mysql_query(
    "INSERT INTO results (generation, number, ref) VALUES (0, $start_number, '$ref')"
  );

  for ($x=1; $x<=max_gens; $x++) {
    mysql_query(
  "INSERT INTO results (generation, number, ref)
  SELECT $x, father, '$ref'
  FROM yourtable yt JOIN results rs ON yt.number=results.number 
  WHERE rs.generation=$x-1
  UNION 
  SELECT $x, mother, '$ref'
  FROM yourtable yt JOIN results rs ON yt.number=results.number 
  WHERE rs.generation=$x-1"
     );
  }

(但有更多错误检查 - 并记得稍后清除数据)

【讨论】:

    【解决方案2】:

    更新了 essam eg 的解决方案 - 现在可以正常工作了:
    - 在循环中首先删除 MAX_GET 之前的 char $
    - 移除循环中的 $generation($i 足够)
    - 在 ($out[$i][] = $record[m_number]; -> $out[$i][] = detail($record[m_number]);) 中添加通话详情br> - 修改添加父亲到数组(母亲两次,父亲失踪)

    define("MAX_GEN",5);
    
    function detail($number) {
        $d = mysql_query("select * from table where number = '$number'");
        if(mysql_num_rows($d) == 0) {
            $p[name] = "N/A";
            $p[number] = "N/A";
            $p[m_number] = "N/A";
            $p[f_number] = "N/A";
        }
        else $p = mysql_fetch_assoc($d);
        return $p;
    }
    
    $main_person_number=001;//number in database
    $out[0][] =detail($number);// main person
    
    
    for($i=1;$i<MAX_GEN;$i++){
      $parent=$i-1;
      for($j=0;$j<pow(2,$parent);$j++){
          $record = detail($out[$parent][$j]['number']);
      $out[$i][] = detail($record[m_number]);
      $out[$i][] = detail($record[f_number]);
        }
    }
    

    【讨论】:

      【解决方案3】:

      我更喜欢使用迭代来创建$out数组

      代替gen函数

      迭代次数增加 1 -> 2 -> 4 ->8

      = 2 ^($generation-1)

      $parent=$generation-1;
            for($j=0;$j<pow(2,$parent);$j++){
      

      完整代码

      define("MAX_GEN",5);
      
      function detail($number) {
          $d = mysql_query("select * from table where number = '$number'");
          if(mysql_num_rows($d) == 0) {
              $p[name] = "N/A";
              $p[number] = "N/A";
              $p[m_number] = "N/A";
              $p[f_number] = "N/A";
          }
          else $p = mysql_fetch_assoc($d);
          return $p;
      }
      
      $main_person_number=001;//number in database
      $generation = 0;
      $out[0][] =detail($number);// main person
      $generation++; // next generation
      
      for($i=1;$i<$MAX_GEN;$i++){
        $parent=$generation-1;
        for($j=0;$j<pow(2,$parent);$j++){
            $record = detail($out[$parent][$j]['number']);
        $out[$generation][] =$record[m_number];
        $out[$generation][] =$record[m_number];
          }
         $generation++;   
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-25
        • 1970-01-01
        • 1970-01-01
        • 2017-03-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多