C#挑战员工树

问题描述:

我有一个c#项目,并且我创建了一个名为Employees的类。
这个类里面,我有一个新的列表:C#挑战员工树

public class Employees 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public int? ManagerId { get; set; } 
    public List<Employees> employees { get; set; } 
} 

想象一下,我已经在图像中显示的结构如下:
companytree

然后在主程序中,我有这样的结构来表示上面的图片:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var root = new Employees() 
     { 
      Id = 15, 
      Name = "President", 
      employees = new List<Employees>() 
      { 
       new Employees() { 

        Id = 23, ManagerId = 15, Name = "Director23", 
        employees = new List<Employees>() 
        { 
         new Employees() { 
          Id = 21, ManagerId = 23, Name = "Manager21", 
          employees = new List<Employees>() 
          { 
           new Employees() { Id = 31, ManagerId=21, Name = "Employee31" }, 
           new Employees() { Id = 41, ManagerId=21, Name = "Employee41" }, 
           new Employees() { Id = 51, ManagerId=21, Name = "Employee51" } 
          } 
         }, 

         new Employees() { 
          Id = 22, ManagerId = 23, Name = "Manager22", 
          employees = new List<Employees>() 
          { 
           new Employees() { Id = 32, ManagerId=22, Name = "Employee32" }, 
           new Employees() { Id = 42, ManagerId=22, Name = "Employee42" }, 
           new Employees() { Id = 52, ManagerId=22, Name = "Employee52" } 
          } 
         } 
        } 
       }, 

       new Employees() { 

        Id = 25, ManagerId = 15, Name = "Director25", 
        employees = new List<Employees>() 
        { 
         new Employees() { 
          Id = 51, ManagerId = 25, Name = "Manager51", 
          employees = new List<Employees>() 
          { 
           new Employees() { Id = 61, ManagerId=51, Name = "Employee61" }, 
           new Employees() { Id = 71, ManagerId=51, Name = "Employee71" }, 
           new Employees() { Id = 81, ManagerId=51, Name = "Employee81" } 
          } 
         }, 

         new Employees() { 
          Id = 62, ManagerId = 25, Name = "Manager62", 
          employees = new List<Employees>() 
          { 
           new Employees() { Id = 72, ManagerId=62, Name = "Employee72" }, 
           new Employees() { Id = 82, ManagerId=62, Name = "Employee82" } 
          } 
         } 
        } 
       } 

      } 
     }; 

     Console.ReadLine(); 
    } 
} 

如何创建一个函数,我传递员工的树根目录和公司的任何员工的ID你需要让你的经理更接近或更高,还有员工本身。

记住,你可以通过一个董事的ID(你将不得不退回总裁),经理的ID(你必须退回董事),员工的ID(你必须返回经理),总统的身份证自己归还。

考虑到我们可以有比这个例子更大的层次结构,做什么更好的方法来做这项研究。扫描所有列表的成本很高。

使用hastable,dictionary,hashset?

+0

你应该在你的命名规则和外壳...'Employees'工作不应该是你的类名,它应该是'员工'(它是一个单一的实体)。 '雇员'应该是'下属'或者_actually_描述它是什么的东西。千万不要混淆像这样的套管。 – maccettura

+0

我同意你的感谢,在急于发贴时我犯下这个错误应该是Employee。这些类的结构并不是真实的,而仅仅是为了展示我们如何在这个树结构中进行这项研究 – devweb

+0

到目前为止,你有什么尝试? –

递归函数通常用于搜索树。我以为你解决这个变量名的建议:

public static Employee FindById(Employee root, int id) { 
    if (root.Id == id) 
     return root; 
    else if (root.Employees != null) { 
     foreach (var e in root.Employees) { 
      var pe = FindById(e, id); 
      if (pe != null) 
       return pe; 
     } 
    } 
    return null; 
} 

要使用,找到员工,然后经理:

var emp = FindById(root, 51); 
var manager = emp.ManagerId.HasValue ? FindById(root, emp.ManagerId.Value) : null; 
+0

是的,我用名称作为示例。您的解决方案有效,但我正在寻找不要多次阅读所有树,并改进搜索。我不知道你想要在字典或HashSet中转换该列表(树)? – devweb

+0

那么,在这种情况下,可能一棵树不是适当的数据结构。 @DependencyInjection答案建议将树转换为一个'Dictionary'并使用它,虽然它没有错误检查,但我看到的主要问题是更新树时会发生什么? – NetMage

添加有两个功能:

public static IDictionary<int, Employees> EmployeesToDictionary(Employees employees) 
{ 
    var dictionary = new Dictionary<int, Employees>(); 
    EmployeesToDictionary(employees, dictionary); 
    return dictionary; 
} 

private static void EmployeesToDictionary(Employees employees, IDictionary<int, Employees> dictionary) 
{ 
    if (employees == null) return; 
    dictionary.Add(employees.Id, employees); 
    if (employees.employees == null) return; 
    foreach (var sub in employees.employees) 
    { 
     EmployeesToDictionary(sub); 
    } 
} 

与用法:

var id = 5; 
var dict = EmployeesToDictionary(root); 
var employee = dict[id]; 
var manager = dict[employee.ManagerId.Value]; 

编辑: @haindl文档是承认失败是的,你是对的。 @devweb我添加了异常检查。该dictionnary创建只有一次,再次检查

+0

欢迎来到StackOverflow!如果你能够解释一下你的代码会很好,所以我们可以理解你提出的答案。 – haindl

+0

似乎是一个使用C#7本地函数的好地方。 – NetMage

+0

在“public static IDictionary EmployeesToDictionary(Employees employees)”中,您不能使用“var dictionary = new Dictionary ();”因为你总是再次创建词典。同样如果你有一个没有孩子的员工,这将会给你一个例外。 – devweb

如果你想要做一个遍历只有一次,有这种可能性:

public static void FindById(Employees root, int id, out Employees employees, out Employees manager) 
{ 
    employees = manager = null; 
    // todo stack 
    var stack = new Stack<Employees>(); 
    stack.Push(root); 
    // all managers seens 
    var managers = new List<Employees>(); 
    while (stack.Count > 0) 
    { 
     var e = stack.Pop(); 
     if (e.Id == id) // if found 
     { 
      employees = e; 
      manager = managers.FirstOrDefault(m => m.Id == e.ManagerId); 
      return; 
     } 
     else if (e.employees != null) 
     { 
      // add only managers with employee 
      managers.Add(e); 
      foreach (var ep in e.employees) 
      { 
       stack.Push(ep); 
      } 
     } 
    } 
}