2015-08-30 19 views
2

我有一个大学项目,我必须逐级打印不同班级学生之间的关系。这个想法是,如果我们有约翰和克里斯在同一班上学习,他们是第一级的朋友,如果克里斯在同一班上学习数学,那么约翰和数学是第二级的朋友。我研究这个问题,我发现算法,如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)) 

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

回答

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; 
    } 
} 
0

在递归过程中的逻辑是不正确的。示例:

假设您输入某个级别A的过程,并且实际上有2个学生在该级别连接。

您处理第一个,分配正确的级别A,标记为“访问”。

然后,在进入第二个之前,您为第一个学生处理A + 1级。在他的“连锁店”某处,你可能会发现第二名正在等待A级处理的学生。然而,他现在被分配了更高一级的A + n,然后被标记为已访问。

接下来,当student1的递归完成时,您继续第二个。然而,他已经“访问”...

(顺便说一句,我不太明白(但我的PHP是弱...)为什么你第一次调用GetRelations指定水平= 2。)

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

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

然后,对于选择的“startStudent”,给自己的水平= 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; 
    } 

希望这可以帮助你。当然,你仍然需要填写树/印刷材料;我的贡献只涉及正确分配级别的逻辑。

+0

是的,我的第一个想法是完全错误的,我在这里错过了一些代码,但你可以在下面检查我自己的答案,并给出你的意见。 – Lexx

+0

对我来说似乎还可以(但我需要再次强调我对PHP不熟悉)。不过,我确实有几个问题:a)我不太明白为什么你的PrintStudent方法有一个参数$ lvl; b)在我看来,$ lvl的初始值应该是零,但是代码表明它是1.因此(c)你有多少个测试用例运行并检查,并且是否有失败? –

+0

$ lvl是一个可选参数,它可以是0或1,它只是从我解决问题的尝试中留下的。我尝试了不同的场景,到目前为止它没有错误地打印学生,没有重印已经打印的连接。它也起作用,因此它只显示最短的连接。 – Lexx