teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

深さ優先探索について言及

2016/08/31 15:45

投稿

MakeNowJust
MakeNowJust

スコア545

answer CHANGED
@@ -1,4 +1,4 @@
1
- このような場合はリストのまま検索しようとせずTreeを最初に構築してから、Treeを再帰的に走査するように検索していくと綺麗に実装できると思います。
1
+ このような場合はリストのまま検索しようとせずTreeを最初に構築してから、Treeを深さ優先探索で走査するように検索していくと綺麗に実装できると思います。
2
2
 
3
3
  それっぽいサンプルコードを書いてみました。質問にあるコードと`Person`のプロパティ名が違うのは`Person`クラスのプロパティに`Person`と付いているのは冗長だからです。それと`Person`にコンストラクタとコピーコンストラクタを追加しています。
4
4
 
@@ -7,49 +7,63 @@
7
7
  using System.Collections.Generic;
8
8
  using System.Linq;
9
9
 
10
- public class SearchTree {
10
+ public class SearchTree
11
+ {
11
- public static void Main() {
12
+ public static void Main()
13
+ {
12
- var persons = new List<Person>();
14
+ var persons = new List<Person>()
15
+ {
13
- persons.Add(new Person("1", null, "山田一郎"));
16
+ new Person("1", null, "山田一郎"),
14
- persons.Add(new Person("2", "1", "山田二郎"));
17
+ new Person("2", "1", "山田二郎"),
15
- persons.Add(new Person("3", "1", "田中太郎"));
18
+ new Person("3", "1", "田中太郎"),
16
- persons.Add(new Person("4", "3", "田中二郎"));
19
+ new Person("4", "3", "田中二郎"),
17
- persons.Add(new Person("5", "3", "鈴木花子"));
20
+ new Person("5", "3", "鈴木花子"),
21
+ };
18
22
  var searcher = new PersonSearcher(persons);
19
23
  var searched = searcher.Search("二郎");
20
24
  ShowPersons(searched, "");
21
25
  }
22
26
 
23
- static void ShowPersons(List<Person> persons, string indent = "") {
27
+ static void ShowPersons(List<Person> persons, string indent = "")
28
+ {
24
- foreach (var person in persons) {
29
+ foreach (var person in persons)
30
+ {
25
31
  Console.WriteLine(indent + "- " + person.Name);
26
- if (person.Children != null) {
32
+ if (person.Children != null)
33
+ {
27
34
  ShowPersons(person.Children, indent + " ");
28
35
  }
29
36
  }
30
37
  }
31
38
  }
32
39
 
33
- class PersonSearcher {
40
+ class PersonSearcher
41
+ {
34
42
  // 親のいないPersonのリスト
35
43
  private List<Person> Founders = new List<Person>();
36
44
  // Person.IdからPersonを参照するためのディクショナリ
37
45
  private Dictionary<String, Person> PersonDictionary = new Dictionary<String, Person>();
38
46
 
39
- public PersonSearcher(List<Person> persons) {
47
+ public PersonSearcher(List<Person> persons)
48
+ {
40
49
  // PersonDictionaryとFoundersの構築
41
- foreach (var person in persons) {
50
+ foreach (var person in persons)
51
+ {
42
- if (person.ParentId == null) {
52
+ if (person.ParentId == null)
53
+ {
43
54
  Founders.Add(person);
44
55
  }
45
56
  PersonDictionary.Add(person.Id, person);
46
57
  }
47
58
 
48
59
  // Personのツリーを構築
49
- foreach (var person in persons) {
60
+ foreach (var person in persons)
61
+ {
50
- if (person.ParentId != null) {
62
+ if (person.ParentId != null)
63
+ {
51
64
  var parent = PersonDictionary[person.ParentId];
52
- if (parent.Children == null) {
65
+ if (parent.Children == null)
66
+ {
53
67
  parent.Children = new List<Person>();
54
68
  }
55
69
  parent.Children.Add(person);
@@ -57,22 +71,28 @@
57
71
  }
58
72
  }
59
73
 
60
- public List<Person> Search(string query) {
74
+ public List<Person> Search(string query)
75
+ {
61
76
  // 親のいないPersonから検索を始める
62
77
  return SearchInternal(Founders, query);
63
78
  }
64
79
 
65
- private List<Person> SearchInternal(List<Person> persons, string query) {
80
+ private List<Person> SearchInternal(List<Person> persons, string query)
81
+ {
66
- return persons.Select(person => {
82
+ return persons.Select(person =>
83
+ {
67
84
  // 名前に含まれている場合はツリーをそのまま返す
68
- if (person.Name.Contains(query)) {
85
+ if (person.Name.Contains(query))
86
+ {
69
87
  return person;
70
88
  }
71
89
  // 子供がいる場合はそれも検索する
72
- if (person.Children != null) {
90
+ if (person.Children != null)
91
+ {
73
92
  var newChildren = SearchInternal(person.Children, query);
74
93
  // 検索結果が0ではなければその検索結果を含んだPersonを新規に作る
75
- if (newChildren.Count() > 0) {
94
+ if (newChildren.Count() > 0)
95
+ {
76
96
  var newPerson = new Person(person);
77
97
  newPerson.Children = newChildren;
78
98
  return newPerson;
@@ -89,13 +109,15 @@
89
109
  public string Name { get; set;}
90
110
  public List<Person> Children { get; set;}
91
111
 
92
- public Person(string id, string parentId, string name) {
112
+ public Person(string id, string parentId, string name)
113
+ {
93
114
  Id = id;
94
115
  ParentId = parentId;
95
116
  Name = name;
96
117
  }
97
118
 
98
- public Person(Person person) {
119
+ public Person(Person person)
120
+ {
99
121
  Id = person.Id;
100
122
  ParentId = person.ParentId;
101
123
  Name = person.Name;