目的
Unityにおいてメッシュを切断するためドロネー三角形分割を実装しました。
ドロネーグラフ(ドロネー木)の実装のため以下の情報を参考にして非巡回有効グラフ(DAG)を実装しました。
An Extensive Examination of Data Structures Using C# 2.0 Part3
An Extensive Examination of Data Structures Using C# 2.0 Part5
ドロネーグラフの接続先が無いノードを重複無しで取り出すことができれば三角形分割を取り出すことができます。
#対応
そこでグラフの全要素を重複無しで取り出すために以下のような実装をしました。
- グラフに全ノードを格納するリストを作る。
- ノード追加(AddDirectedEdge)時に全ノードリストにあるノードと重複するか確認する。
- 重複していなければ全ノードリストに格納、そうでない場合は何もしない。
#問題
前述の方法ではノード追加時の重複チェックにO(n)の計算量を必要とします。(nはグラフのノード数)
ノード追加は頻繁に行うため、できれば定数時間に落としたいです。
また、O(n)程度でDAGの重複無し全要素を取得するアルゴリズムがあればお教えいただきたいです。
#実装
この実装は以下の実装から重みを省いて前述の対応を追加したものです。
An Extensive Examination of Data Structures Using C# 2.0 Part3
An Extensive Examination of Data Structures Using C# 2.0 Part5
C#
1using System.Collections; 2using System.Collections.Generic; 3public class Graph<T> : IEnumerable<T> 4{ 5 private NodeList<T> nodeSet; 6 public NodeList<T> allNode = new NodeList<T>(); 7 8 public Graph() : this(null) { } 9 public Graph(NodeList<T> nodeSet) 10 { 11 if (nodeSet == null) 12 this.nodeSet = new NodeList<T>(); 13 else 14 this.nodeSet = nodeSet; 15 } 16 public void AddNode(GraphNode<T> node) 17 { 18 nodeSet.Add(node); 19 allNode.Add(node); 20 } 21 public void AddNode(T value) 22 { 23 nodeSet.Add(new GraphNode<T>(value)); 24 } 25 public void AddDirectedEdge(GraphNode<T> from, GraphNode<T> to) 26 { 27 from.Neighbors.Add(to); 28 if (!allNode.Contains(to)) 29 allNode.Add(to); 30 } 31 public bool Contains(T value) 32 { 33 return nodeSet.FindByValue(value) != null; 34 } 35 public bool Remove(T value) 36 { 37 GraphNode<T> nodeToRemove = (GraphNode<T>)nodeSet.FindByValue(value); 38 if (nodeToRemove == null) 39 return false; 40 41 nodeSet.Remove(nodeToRemove); 42 43 foreach (GraphNode<T> gnode in nodeSet) 44 { 45 int index = gnode.Neighbors.IndexOf(nodeToRemove); 46 if (index != -1) 47 gnode.Neighbors.RemoveAt(index); 48 } 49 50 return true; 51 } 52 public IEnumerator<T> GetEnumerator() 53 { 54 return (IEnumerator<T>)allNode.GetEnumerator(); 55 } 56 IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } 57 public NodeList<T> NodeList 58 { 59 get { return nodeSet; } 60 } 61}
C#
1public class GraphNode<T> : Node<T> 2{ 3 public GraphNode() : base() { } 4 public GraphNode(T value) : base(value) { } 5 public GraphNode(T value, NodeList<T> neighbors) : base(value, neighbors) { } 6 7 new public NodeList<T> Neighbors 8 { 9 get 10 { 11 if (base.Neighbors == null) 12 base.Neighbors = new NodeList<T>(); 13 return base.Neighbors; 14 } 15 } 16}
C#
1public class Node<T> 2{ 3 private T data; 4 private NodeList<T> neighbors = null; 5 6 public Node() { } 7 public Node(T data) : this(data, null) { } 8 public Node(T data, NodeList<T> neighbors) 9 { 10 this.data = data; 11 this.neighbors = neighbors; 12 } 13 public T Value 14 { 15 get 16 { 17 return data; 18 } 19 set 20 { 21 data = value; 22 } 23 } 24 protected NodeList<T> Neighbors 25 { 26 get 27 { 28 return neighbors; 29 } 30 set 31 { 32 neighbors = value; 33 } 34 } 35}
C#
1using System.Collections.ObjectModel; 2 3public class NodeList<T> : Collection<Node<T>> 4{ 5 public NodeList() : base() { } 6 public NodeList(int initialSize) 7 { 8 for (int i = 0; i < initialSize; i++) 9 base.Items.Add(default(Node<T>)); 10 } 11 public Node<T> FindByValue(T value) 12 { 13 foreach (Node<T> node in Items) 14 if (node.Value.Equals(value)) 15 return node; 16 17 return null; 18 } 19}
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/12/11 12:34 編集