-
Notifications
You must be signed in to change notification settings - Fork 1
/
GraphEdge.java
221 lines (205 loc) · 7.08 KB
/
GraphEdge.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/**
*
*/
package it.unicam.cs.asdl2122.pt1;
/**
* Questa classe raggruppa le caratteristiche di un arco, possibilmente pesato
* ed etichettato, facente parte di un grafo. I nodi del grafo sono etichettati
* con oggetti della classe {@code L}. Le classi {@code GraphNode<L>} e
* {@code Graph<L>} definiscono le operazioni generiche sui nodi e sul grafo,
* rispettivamente.
*
* Un arco può essere orientato o non orientato, tale informazione è immutabile
* e disponibile tramite il metodo {@code isDirected()}. I due nodi collegati
* dall'arco sono immutabili e non possono essere nulli.
*
* All'arco può essere associato un peso tramite i metodi
* {@code setWeight(double} e {@code getWeight()}. Il peso, se non specificato
* nel costruttore, è inizializzato automaticamente a {@code Double.NaN}. In tal
* caso l'arco è considerato non pesato fino a quando non gli viene assegnato un
* valore diverso da Double.NaN.
*
* Due archi sono uguali se e solo se collegano gli stessi nodi e sono entrambi
* orientati o entrambi non orientati. Nel caso di archi non orientati l'ordine
* dei nodi non conta, cioè un arco tra {@code n1} ed {@code n2} e un arco tra
* {@code n2} ed {@code n1} sono considerati lo stesso arco.
*
* @author Luca Tesei
*
* @param <L>
* tipo delle etichette dei nodi del grafo
*
*/
public class GraphEdge<L> {
private final GraphNode<L> node1;
private final GraphNode<L> node2;
private final boolean directed;
private double weight;
/**
* Costruisce un arco pesato di un grafo.
*
* @param node1
* primo nodo (nodo sorgente in caso di grafo orientato)
* @param node2
* secondo nodo (nodo destinazione in caso di grafo
* orientato)
* @param directed
* true se l'arco è orientato, false altrimenti
* @param weight
* peso associato all'arco
*
* @throws NullPointerException
* se almeno uno dei due nodi è nullo
*/
public GraphEdge(GraphNode<L> node1, GraphNode<L> node2, boolean directed,
double weight) {
if (node1 == null)
throw new NullPointerException("Nodo 1 dell'arco nullo");
if (node2 == null)
throw new NullPointerException("Nodo 2 dell'arco nullo");
this.node1 = node1;
this.node2 = node2;
this.directed = directed;
this.weight = weight;
}
/**
* Costruisce un arco di un grafo.
*
* @param node1
* primo nodo (nodo sorgente in caso di grafo orientato)
* @param node2
* secondo nodo (nodo destinazione in caso di grafo
* orientato)
* @param directed
* true se l'arco è orientato, false altrimenti
*
* @throws NullPointerException
* se almeno uno dei due nodi è nullo
*/
public GraphEdge(GraphNode<L> node1, GraphNode<L> node2, boolean directed) {
if (node1 == null)
throw new NullPointerException("Nodo 1 dell'arco nullo");
if (node2 == null)
throw new NullPointerException("Nodo 2 dell'arco nullo");
this.node1 = node1;
this.node2 = node2;
this.directed = directed;
this.weight = Double.NaN;
}
/**
* Determina se questo arco è attualmente pesato.
*
* @return true se questo arco ha attualmente associato un peso diverso da
* Double.NaN
*/
public boolean hasWeight() {
return !Double.isNaN(this.weight);
}
/**
* Restituisce il primo nodo di questo arco, la sorgente in caso di arco
* orientato.
*
* @return il primo nodo di questo arco, la sorgente in caso di arco
* orientato.
*/
public GraphNode<L> getNode1() {
return this.node1;
}
/**
* Restituisce il secondo nodo di questo arco, la destinazione in caso di
* arco orientato.
*
* @return il secondo nodo di questo arco, la destinazione in caso di arco
* orientato.
*/
public GraphNode<L> getNode2() {
return this.node2;
}
/**
* Indica se questo arco è orientato o no.
*
* @return true se questo arco è orientato, false altrimenti.
*/
public boolean isDirected() {
return this.directed;
}
/**
* Restituisce il peso assegnato all'arco. Nel caso in cui il peso è uguale
* a Double.Nan l'arco è da considerarsi attualmente non pesato.
*
* @return il peso associato all'arco
*/
public double getWeight() {
return this.weight;
}
/**
* Assegna un certo peso a questo arco.
*
* @param weight
* il peso da assegnare a questo arco
*/
public void setWeight(double weight) {
this.weight = weight;
}
/*
* Basato sul flag che definisce se l'arco è orientato o no e sugli hashCode
* dei due nodi collegati.
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (directed ? 1231 : 1237);
// Modificata l'implementazione standard per rispettare la proprietà
// dell'hashCode anche nel caso di archi non orientati con ordine
// diverso
result = prime * result + (node1.hashCode() + node2.hashCode());
return result;
}
/*
* Due archi sono uguali se sono entrambi orientati o non orientati e se
* collegano nodi uguali. Nel caso in cui l'arco non sia orientato l'ordine
* dei nodi non conta.
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof GraphEdge))
return false;
GraphEdge<?> other = (GraphEdge<?>) obj;
if (directed != other.directed)
return false;
// C'è differenza tra caso non orientato e caso orientato
if (directed) {
if (!node1.equals(other.node1))
return false;
if (!node2.equals(other.node2))
return false;
return true;
} else { // caso speciale per grafi non orientati
// ci deve essere una uguaglianza diretta o incrociata
if (node1.equals(other.node1) && node2.equals(other.node2))
return true;
if (node1.equals(other.node2) && node2.equals(other.node1))
return true;
// Altrimenti non sono uguali
return false;
}
}
@Override
public String toString() {
if (this.directed)
return "Edge [ " + this.node1.toString() + " --> "
+ this.node2.toString() + " ]";
else
return "Edge [ " + this.node1.toString() + " -- "
+ this.node2.toString() + " ]";
}
}