가장자리는 참조 정점, 정점은 참조 가장자리입니다. 나는 이것이 자연스러운 것이라고 생각한다.
이것은 잘못된 가정입니다. 정점을 가장자리로 가리키는 자연스러운 것은 이 아니고, 정점을 가리키는 가장자리가 있습니다.입니다. 하나는 다른 하나를 참조해야하며 둘 다 서로를 참조하지는 않습니다. 참조 책임이 중복되면 모든 문제가 발생할 수 있습니다. 예를 들어, 동기화가되지 않으면 그래프를 다시 작성할 수있는 진실의 원천이 없습니다.
순환 의존성을 피하려면 관계의 "소유자"가 하나 있어야합니다. 특정 예에서, 정점을 참조 모서리은과 같이 "소유자"더 확실한 인상을 받았는데 그런 다음
// edge.js
goog.provide('Edge');
goog.require('Vertex');
goog.require('goog.math.Coordinate');
/**
* @constructor
* @param {Vertex} start
* @param {Vertex} end
*/
Edge = function(start, end) {
/**
* @type {Vertex}
* @private
*/
this.start_ = start;
/**
* @type {Vertex}
* @private
*/
this.end_ = end;
};
/**
* @return {number}
*/
Edge.prototype.getDistance = function() {
goog.math.Coordinate.distance(this.start_, this.end_);
};
/**
* Checks if this Edge connects to the referenced vertex.
* @param {Vertex} vertex
* @return {bool}
*/
Edge.prototype.connects = function(vertex) {
return this.start_ === vertex || this.end_ === vertex;
};
/**
* @return {Vertex}
*/
Edge.prototype.getStart = function() {
return this.start_;
};
/**
* @return {Vertex}
*/
Edge.prototype.getEnd = function() {
return this.end_;
};
그래프 ... ... 그런
// vertex.js
goog.provide('Vertex');
goog.require('goog.math.Coordinate');
/**
* @constructor
* @param {number=} opt_x x-position, defaults to 0
* @param {number=} opt_y y-position, defaults to 0
* @extends {goog.math.Coordinate}
*/
Vertex = function(opt_x, opt_y) {
goog.base(this, opt_x, opt_y);
};
에지
/**
* @param {Array.<Edge>} edges
* @constructor
*/
Graph = function(edges) {
/**
* @type {Array.<Edge>}
* @private
*/
this.edges_ = edges;
};
/**
* @param {Vertex} start
* @param {Vertex} end
* @return {number|undefined} shortest path between {@code start} and {@code end},
* with 'undefined' being returned if a path does not exist.
*/
Graph.prototype.getShortestPath = function(start, end) {
return this.getShortestPath_(start, end, 0, []);
}
/**
* @param {Vertex} start
* @param {Vertex} end
* @param {number} traveled amount traveled thus far
* @param {Array.<Vertex>} path the route taken thus far
* @return {number|undefined}
* @private
*/
Graph.prototype.getShortestPath_ = function(start, end, traveled, path) {
if (start == end) {
return traveled + 0;
}
var distances = goog.array.map(
this.getEdgesToTry_(start, path),
function (edge) {
var nextStart;
if (edge.getStart() === start) {
nextStart = edge.getEnd();
} else {
nextStart = edge.getStart();
}
return this.getShortestPath_(
newStart,
end,
edge.getDistance() + traveled,
goog.array.concat(path, start)
);
},
this
);
return goog.array.reduce(
distances,
function (shortestDistance, distance) {
if (distance !== undefined) {
if (shortestDistance === undefined) {
return distance;
} else {
return Math.min(shortestDistance, distance);
}
} else {
return shortestDistance;
}
},
undefined
);
};
/**
* @param {Vertex} vertex
* @param {Array.<Vertex>} path
* @return {Array.<Vertex>}
* @private
*/
Graph.prototype.getEdgesToTry_ = function(vertex, path) {
return goog.array.filter(
this.edges_,
function (edge) { return this.isEdgeToTry_(edge, vertex, path); },
this
);
};
/**
* @param {Edge} edge
* @param {Vertex} start
* @param {Array.<Vertex>} path
* @return {bool}
* @private
*/
Graph.prototype.isEdgeToTry_ = function(edge, start, path) {
return edge.connects(start)
&& goog.array.every(
path, function(vertex) { return !edge.connects(vertex); });
};
경고 : 나는 이것을 시험하지 않았다. 그것은 some nice Puerto Rican rum 병을 통해 해킹 한 것입니다. 아마 여기 저기에 뭔가 엉망이 될 수도 있습니다. 그럼에도 불구하고, 개념은 의미한다. 그래프에 대한 질문에 답하기 위해 특정 언어 나 기술에 순환 종속성이 필요하지는 않습니다 (솔직히 바람직합니다).