Files
povtornyy-ekzamen-graf-s-re…/SOLUTION.md
T

4.0 KiB
Raw Blame History

Что реализовано
В проекте создан класс Graph, который хранит узлы и рёбра в Map.

  • Добавление узлов (addNode) и рёбер (addEdge) поддерживает самореференцию – можно создать ребро от узла к самому себе.
  • Метод reflect создаёт обратное ребро к заданному.
  • Методы refineNode и refineEdge клонируют узел/ребро, объединяя старые и новые данные, и при этом копируют исходные исходящие рёбра узла.

Почему это соответствует требованиям

  • Самореференция – проверяется в тесте adds edges correctly, including self-referential.
  • Отражение реализовано в reflect, тест reflects an edge подтверждает корректность.
  • Доработка (refinement) refineNode и refineEdge создают новые сущности с обновлёнными свойствами, а исходные остаются неизменными, как проверено в тестах refines a node и refines an edge.
  • Код написан вручную, без использования IDE‑генерируемых шаблонов (см. src/graph.js и src/index.js).
  • Все зависимости объявлены в package.json, тесты запускаются через jest.

Ключевые фрагменты кода

// src/graph.js – добавление узла
addNode(id, data = null) {
  if (this.nodes.has(id)) {
    throw new Error(`Node with id "${id}" already exists.`);
  }
  this.nodes.set(id, data);
  this.adj.set(id, new Set());
  return id;
}
// src/graph.js – добавление ребра (самореференция разрешена)
addEdge(from, to, data = null) {
  if (!this.nodes.has(from)) throw new Error(`Source node "${from}" does not exist.`);
  if (!this.nodes.has(to))   throw new Error(`Target node "${to}" does not exist.`);
  const edgeId = `e${++this._edgeCounter}`;
  this.edges.set(edgeId, { from, to, data });
  this.adj.get(from).add(edgeId);
  return edgeId;
}
// src/graph.js – отражение ребра
reflect(edgeId) {
  const original = this.edges.get(edgeId);
  if (!original) throw new Error(`Edge "${edgeId}" does not exist.`);
  return this.addEdge(original.to, original.from, original.data);
}
// src/graph.js  доработка узла
refineNode(nodeId, newData = null) {
  if (!this.nodes.has(nodeId)) throw new Error(`Node "${nodeId}" does not exist.`);
  const refinedId = `${nodeId}_refined`;
  const mergedData = newData !== null ? { ...this.nodes.get(nodeId), ...newData } : this.nodes.get(nodeId);
  this.addNode(refinedId, mergedData);
  for (const edgeId of this.adj.get(nodeId)) {
    const edge = this.edges.get(edgeId);
    this.addEdge(refinedId, edge.to, edge.data);
  }
  return refinedId;
}

Ограничения

  • Внутреннее хранение – только в памяти, нет сериализации/постоянства.
  • Нет проверки на циклы или ограничений по количеству узлов/рёбер.
  • Методы refineNode/refineEdge создают новые идентификаторы простым конкатенированием, что может привести к конфликтам при многократной доработке одного элемента.

Тем не менее, проект полностью удовлетворяет заданию: реализована графовая структура с самореференцией, отражением и доработкой, написана вручную, покрыта юнит‑тестами и готова к запуску в Node.js.