打印成员之间的关系

时间:2015-08-30 10:48:28

标签: php algorithm oop binary-tree

我是一个大学项目,我可以逐层打印不同班级学生之间的关系。我们的想法是,如果我们让约翰和克里斯在同一个班级学习,他们就是第一级的朋友,如果克里斯在同一个班级学习数学,那么约翰和数学就是二级的朋友。我研究了这个问题,我找到了像this这样的算法,但我的主要问题是我使用对象作为输入数据:

<?php
class Student {

 private $id = null;
 private $classes = [];

 public function __construct($id) {
   $this->id = $id;
 }

 public function getId() {
   return $this->id;
 }

 public function getClasses() {
   return $this->classes;
 }

 public function addClass(UClass $class) {
   array_push($this->classes, $class);
 }

}

class UClass {

 private $id = null;
 private $students= [];

 public function __construct($id) {
   $this->id = $id;
 }

 public function getId() {
   return $this->id;
 }

 public function getStudents() {
   return $this->students;
 }

 public function addStudent(Student $student) {
   array_push($this->students, $student);
   $student->addClass($this);
 }

}

function getRelations(Student $start_student, &$tree = array(), $level = 2, &$visited) {
 foreach ($start_student>Classes() as $class) {    
   foreach ($class->Students() as $student) {
     if($start_student->getId() != $student->getId() && !is_int(array_search($student->getId(), $visited))) {
         $tree[$level][] = $student->getId();
         array_push($visited, $student->getId());
         getRelations($student, $tree, $level+1, $visited); 
     }
   }
 }
}

$class = new UClass(1);
$class2 = new UClass(2);
$class3 = new UClass(3);

$student = new Student(1);
$student2 = new Student(2);
$student3 = new Student(3);
$student4 = new Student(4);
$student5 = new Student(5);
$student6 = new Student(6);

$class->addStudent($student);
$class->addStudent($student2);
$class->addStudent($student4);

$class2->addStudentr($student2);
$class2->addStudent($student4);
$class2->addStudent($student5);

$class3->addStudent($student4);
$class3->addStudent($student5);
$class3->addStudent($student6);

$tree[1][] = $student->getId();
$visited = array($student->getId());
getRelations($student, $tree, 2, $visited);
print_r($tree);

我坚持编写getRelations()函数,该函数应创建类似

的数组
Array ( [1] => Array ( [0] => 1 ) [2] => Array ( [0] => 2 [1] => 4 ) [3] => Array ( [0] => 5 [1] => 6 ) ) 

但是我无法正确地获得递归(或者可能是整个算法)。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

我提出了这个功能(不确定它是否是最佳解决方案,但它适用于类对象)

function print_students(Student $start_student, &$tree = array(), $lvl = 1) {
  if (!$start_student) {
    return;
  }
  $tree[$lvl][] = $start_student->getId();
  $q = array();
  array_push($q, $start_student);
  $visited = array($start_student->getId());

  while (count($q)) {
    $lvl++;
    $lvl_students = array();
    foreach ($q as $current_student) {
      foreach ($current_student->getClasses() as $class) {
        foreach ($class->getStudents() as $student) {
          if (!is_int(array_search($student->getId(), $visited))) {
            array_push($lvl_students, $student);
            array_push($visited, $student->getId());
            $tree[$lvl][] = $student->getId();
          }
        }
      }
    }
    $q = $lvl_students;
  }
}

答案 1 :(得分:0)

递归过程中的逻辑不正确。例如:

假设您输入某个级别A的程序,并且实际上有2名学生可以找到该级别的连接。

您处理第一个,指定正确的A级,将其标记为“已访问”。

然后,在到达第二个之前,您将为第一个学生处理A + 1级。在他的“链”中的某个地方,你也可能找到第二个等待在A级处理的学生。但是,他现在被分配了一些更高级别的A + n,然后被标记为已访问。

接下来,当student1的递归完成后,继续第二次。但是,他已被“访问过”......

(顺便说一句,我不太明白(但我的php很弱......)为什么你第一次调用GetRelations指定level = 2.)

无论如何,为了使你的逻辑正确,不需要递归。

为每个学生添加“级别”属性。把所有学生也放在一个整体的“人口”集合中。

然后,对于选择的“startStudent”,给自己level = 0,所有其他学生等级= -1。

迭代等级并尝试填写友谊等级,直到没有什么可做的。我的php几乎不存在,所以我尝试了一些伪代码。

  for(int level=0; ; level++) // no terminating condition here
   {
      int countHandled = 0;
      for each (student in population.students)
      {
        if (student.level==level)
        {
          for each (class in student.classes)
          {
            for each (student in class.students)
            {
              if(student.level==-1)
              {
                student.level = level+1;
                countHandled++;
              }
            }
          }
        }
      }
      if(countHandled==0)
        break;
    }

希望这会帮助你。当然,你仍然需要填写树/印刷品;我的贡献只涉及正确分配水平的逻辑。