質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

2回答

293閲覧

[Java]頂点に接続する辺をMapを用いて表したい

退会済みユーザー

退会済みユーザー

総合スコア0

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2019/06/06 03:21

編集2019/06/06 03:49

前提・実現したいこと

頂点と辺を持つグラフにおいて、ある頂点に接続する辺を、
HashMap<Node, List<Edge>>
の形で表現したい。
Node:頂点クラス
Edge:辺クラス

Parserを使ったNodeの読み込みのところで、接続する辺のIDを取得できるのですが、
そこからEdge(ID, 端点1, 端点2, 重み)を作成してListに入れ込む方法がわかりません。
そこを教えていただきたいです。よろしくお願いします。ほかの場所でおかしな部分があれば合わせて教えていただきたいです。

Java

1import java.util.*; 2import java.io.*; 3 4public class Graph{ 5 Map<Node, List<Edge>> graph = new HashMap<>(); 6 List<Edge> e = new ArrayList<>(); 7 class Edge{ 8 int id; //辺の識別番号 9 int node1, node2; //辺の両端の頂点 10 int weight; //辺の重み 11 12 Map<Integer, Node> nodes; 13 List<Edge>[] eds; 14 15 Edge(int id, int node1, int node2, int weight){ 16 this.id = id; 17 this.node1 = node1; 18 this.node2 = node2; 19 this.weight = weight; 20 } 21 22 int getNode1(){ 23 return node1; 24 } 25 int getNode2(){ 26 return node2; 27 } 28 int getWeight(){ 29 return weight; 30 } 31 32 // データファイルから生成するコンストラクタ 33 // 頂点(変数)の集合を参照する 34 Edge(Parser p,Map<Integer, Node> nds) throws IOException{ 35 nodes = nds; 36 37 p.getLPar(); 38 id = p.getNumber(); // 辺の識別名 39 System.out.println(" 辺"+id); 40 41 p.getLPar(); // 変数の識別名のリスト(二項関数) 42 node1 = p.getNumber(); 43 System.out.println(" 頂点1="+node1); 44 node2 = p.getNumber(); 45 System.out.println(" 頂点2="+node2); 46 p.getRPar(); 47 weight = p.getNumber(); //辺の重み 48 p.getRPar(); 49 } 50 } 51 52 class Node{ 53 int id; 54 ArrayList<Integer> edges; 55 int x, y; 56 int w; //0:non-taskendpoint, 1:endpoint, 2:taskendpoint 57 List<Edge> eds; 58 59 Node(int id){ 60 this.id = id; 61 this.edges = new ArrayList<Integer>(); 62 } 63 64 ArrayList<Integer> getList(){ //隣接する辺の取得 65 return new ArrayList<>(edges); 66 } 67 68 Node(Parser p) throws IOException{ // データファイルから生成するコンストラクタ 69 p.getLPar(); 70 id = p.getNumber(); // 頂点の識別名 71 System.out.println(" 頂点"+id); 72 //Node node = new Node(id); 73 this.edges = new ArrayList<Integer>(); 74 75 p.getLPar(); // 関数の識別名のリスト 76 while(p.isNumber()){ 77 int a = p.getNumber(); 78 edges.add(a); 79 eds.add(new Edge(a,getNode1(),getNode2(),getWeight())); 80 } 81 p.getRPar(); 82 System.out.println(" 接続する辺の識別名のリスト="+edges); 83 84 85 p.getLPar(); //座標 86 x = p.getNumber(); 87 y = p.getNumber(); 88 p.getRPar(); 89 90 w = p.getNumber(); //属性 91 92 p.getRPar(); 93 } 94 } 95 96}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

swordone

2019/06/06 03:41

マークダウンは正しく使ってください。 コードの前に書いてある"Java"を"```java"と書き直し、 その上の文章を囲っている"```"を消してください。
退会済みユーザー

退会済みユーザー

2019/06/06 03:51

失礼しました。修正方法まで丁寧にありがとうございます。
mather

2019/06/06 05:50

そのMapの場合、構造上同じ Edge が2つの Node について存在することになりますが、その認識で間違いないでしょうか? そもそもParserというものが出てくるということはファイルなどから何かグラフに関するものを読み込んでいるのでしょうか? 問題の背景がさっぱりわからないので回答しにくいです。
mather

2019/06/06 05:52

なお、書き方がわからないって投げ出すのは丸投げに近いです。 eds.add(new Edge(a,getNode1(),getNode2(),getWeight())); などの行は不明な変数など明らかに動かないものが並んでいます。 まずは努力して動く状態を作ってみてはどうでしょうか?
guest

回答2

0

投稿に失敗してました!
解決済みのようですが一応最初に書いた内容をそのまま載せておきます。


NodeとEdgeのように双方が多対多の関係にあるものを読み込む・書き込む際にはファクトリーパターン的に考えるとよいと思います。その片鱗は質問者さんのコードに見え隠れしているのですが・・・

  • NodeやEdgeを直接newしない
  • その替わりに番号を指定して「既にあればそれを返し、なければ生成して返す」ようなファクトリー的なものを考える

ファクトリーは番号に対応したNode/Edgeを覚えておくMapがあれば次のような雰囲気に作れるでしょう。ファクトリーは別にクラスにしなくてもNode/Edgeのstaticなメソッドとしてもよいと思います。

java

1class Node { 2 private static Map<Integer, Node> map = new HashMap<>(); 3 public static Node getInstance(int id) { 4 return map.computeIfAbsent(id, (id) -> new Node(id)); 5 } 6 7 // 自分はfinalかつアクセスしたときに特別なことを特にしなくてよい 8 // と考える場合、一々getterは作りません。 9 public final int id; 10 11 private Node(int id) { 12 this.id = id; 13 } 14 15 ... 16}

こうしておくとNodeやEdgeをどのタイミングで生成すべきかややこしいことを気にしなくてよくなります。このような仕組みにしておくと入力ファイルのフォーマットも自由度が高まります。

(A)

text

13 <- Edgeの数 21 1 2 <- edge#1がノード1, 2を持つという具合 32 2 3 <- 以下同様 4...

ともできますし
(B)

text

13 <- Nodeの数 21 1 3 <- Node#1がEdge#1, Edge#3に繋がっているという具合 32 2 3 <- 以下同様

ともできます。

(A),(B)で変わってくるのは一通り読み込んだ後の後処理的なものです。
(A)ですとEdge側に対応するノードの一覧のListができますがNode側にもEdgeのListを設けたければEdgeのmapを全て調べそこに出現する各々のNodeへEdgeを追加していけばよいですし(B)ならその逆になるだけです。


ちなみに、idのListとオブジェクト実体のListを両方持つのは冗長なので止めたほうがよいでしょう。idあるいはオブジェクトのいずれかのListがあれば済みます。両方もたせると両者を整合させる配慮が面倒になるだけと思います。Mapを用いたルックアップは高速なのでidからオブジェクトを求める処理は充分早いですしオブジェクトがわかればそのidを求めることも簡単です。

どちらかといえばidは表示や読み込みの都合で持たせるものとして考え、オブジェクトのListのみ持たせる方がよいと思います。つまりNodeにはList<Edge>だけ持たせ、EdgeにはList<Node>のみを持たせます。

投稿2019/06/06 03:53

編集2019/06/06 15:45
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

LouiS0616

2019/06/06 13:39

回答の投稿に失敗しているみたいですよ。
KSwordOfHaste

2019/06/06 15:47 編集

あれ!? ---- 質問を編集すると元の投稿内容が残ってたのでとりあえずそのまんま再度投稿してみました。 LouiS0616さん、ご指摘ありがとうございました。
退会済みユーザー

退会済みユーザー

2019/06/07 02:27

ご丁寧にありがとうございます。勉強になりました。
KSwordOfHaste

2019/06/07 02:48

なお、本サイトは「質問者の問題だけ解決すればよい」のではなく「何が問題でどう解決するか」をみんなで共有することに意義を見出す閲覧者が多いですし運営さんもそれを狙っています。そのため例え解決しても「解決しました」の一言では不十分と思います。簡単でもよいので「こういうふうにして解決した」と書いておくことを強くお勧めします(回答も質問も編集できます)。 それを書いたうえで自己解決の操作を行って質問を閉じましょう。解決したにもかかわらず質問を閉じないまま放置するのはマナー違反であることを覚えておいてください。
guest

0

解決しました、ありがとうございました

投稿2019/06/06 13:13

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問