各位大神, |
|
![]() 20分 |
给你写了一个demo
using System; using System.Collections.Generic; using System.Linq; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { List<Question> QuestionList = new List<Question>(); Question Q11 = new Question() { Title = "1.1", Score = 5, }; Question Q12 = new Question() { Title = "1.2", Score = 5, }; Question Q13 = new Question() { Title = "1.3", Score = 5, }; List<Question> Q13List = new List<Question>(); Question Q131 = new Question() { Title = "1.3.1", Score = 5, }; Question Q132 = new Question() { Title = "1.3.2", Score = 5, }; List<Question> Q132List = new List<Question>(); Question Q1321 = new Question() { Title = "1.3.2.1", Score = 5, }; Question Q1322 = new Question() { Title = "1.3.2.2", Score = 5, }; Question Q1323 = new Question() { Title = "1.3.2.3", Score = 5, }; Q132.Questions = Q132List; Q13List.Add(Q131); Q13List.Add(Q132); Q13.Questions = Q13List; List<Question> Q1List = new List<Question>(); Q1List.Add(Q11); Q1List.Add(Q12); Q1List.Add(Q13); Question Q1 = new Question() { Title = "First One", Score = 25, Questions = Q1List, }; Question Q2 = new Question() { Title = "Second", Score = 25, }; Question Q3 = new Question() { Title = "Third", Score = 25, }; QuestionList.Add(Q1); QuestionList.Add(Q2); QuestionList.Add(Q3); var all = GetAll(QuestionList); Console.WriteLine("现在总共有 {0} 个Question。", all.Count()); var search = (from t in all let q = t.Item1 where q.Title == "1.3.2" && q.Score == 5 select t).ToList(); Console.WriteLine("找到{0}个符合条件的Question。", search.Count); if (search.Any(r => r.Item1.Questions != null && r.Item1.Questions.Count > 0)) throw new Exception("Question的Questions集合不是空的,不能删除。"); foreach (var r in search) r.Item2.Questions.Remove(r.Item1); //从父Question的Questions属性中删除子Quenstion Console.WriteLine("总共有 {0} 个Question。", GetAll(QuestionList).Count()); Console.WriteLine("_________________按任意键结束。"); Console.ReadKey(); } /// <summary> /// 返回所有的Question极其父Question。 /// </summary> /// <param name="list">要遍历的树。</param> /// <returns>返回子Question及其父Question的 Tuple 结构列表。 /// 对于顶级Question,则父Question为null。</returns> public static IEnumerable<Tuple<Question, Question>> GetAll(List<Question> list) { foreach (var r in GetAll(list, null)) yield return r; } private static IEnumerable<Tuple<Question, Question>> GetAll(List<Question> list, Question parent) { foreach (var q in list) { yield return new Tuple<Question, Question>(q, parent); var children = q.Questions; if (children != null && children.Count > 0) foreach (var r in GetAll(q.Questions, q)) yield return r; } } } public class Question { public List<Question> Questions { get; set; } public string Title { get; set; } public int Score { get; set; } } } /pre> 要删除它,必须先找到它。而要找到它,就需要递归搜索。 在数据结构上,由于需要知道它的parent才能删除它,因此搜索的结果是得到 Tuple<Question,Question> 这样的“子-父”结构。 在搜索功能上,使用了c#的迭代器功能,方便于将搜索应用到各种灵活的枚举功能的场合。例如使用 Linq 中。 |
![]() 10分 |
这里边有两个功能点:
首先是 GetAll 方法中,使用 5、6行代码对树进行深度优先搜索,并且以c#的迭代器模式输出出来。 第二点就是在数据结构上返回了“子Question与其父Question的元组”。当然你也可以自定义一个有着两个属性的class。关键是要知道返回“两个”属性才够进行后续删除动作。 |
![]() 10分 |
实际开发中,需要反之无限递归的情况出现。(你可以设计一个测试用例,仅仅有2个Questiion,就能产生一个无限递归)
这个你自己修改吧。有多种形式。例如可以在递归查找(第二个Get方法)的参数上增加一个“已经查找出来的Question的收集集合,在 yield return 返回结果之前先判断一下是否重复。或者(更轻量的方式)是在这个方法参数上仅增加一个“递归深度”数值,并且程序判断最多仅递归5层。 |