Skip to content

Commit

Permalink
Деревья
Browse files Browse the repository at this point in the history
  • Loading branch information
Pastor committed Dec 6, 2024
1 parent 0a1f9e6 commit d545588
Show file tree
Hide file tree
Showing 11 changed files with 320 additions and 22 deletions.
46 changes: 46 additions & 0 deletions vol6/src/main/java/ru/mifi/practice/vol6/tree/Diameter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package ru.mifi.practice.vol6.tree;

import ru.mifi.practice.vol6.tree.paths.LowestCommonAncestorPath;
import ru.mifi.practice.vol6.tree.visitors.Distance;

import java.util.List;

public final class Diameter<T> {

public List<Node<T>> path(Tree<T> tree) {
VisitorStrategy.PreOrder<T> strategy = new VisitorStrategy.PreOrder<>();
Distance<T> vDistance = new Distance<>();
tree.visit(vDistance, strategy);
int max = 0;
Node<T> maxNode = null;
for (var entry : vDistance.distances().entrySet()) {
if (max < entry.getValue()) {
max = entry.getValue();
maxNode = entry.getKey();
}
}
if (maxNode != null) {
VisitorStrategy.AlreadyVisited<T> alreadyVisited = new VisitorStrategy.AlreadyVisited<>(strategy);
Node<T> start = maxNode;
Node<T> it = maxNode;
int distance = 0;
vDistance.clear();
while (it != null) {
vDistance.resetLevel(distance);
it.visit(vDistance, alreadyVisited);
++distance;
it = it.parent();
}
max = 0;
for (var entry : vDistance.distances().entrySet()) {
if (max < entry.getValue()) {
max = entry.getValue();
maxNode = entry.getKey();
}
}
Node<T> end = maxNode;
return new LowestCommonAncestorPath<T>().path(tree, start.value(), end.value());
}
return List.of();
}
}
20 changes: 20 additions & 0 deletions vol6/src/main/java/ru/mifi/practice/vol6/tree/Main.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package ru.mifi.practice.vol6.tree;

import ru.mifi.practice.vol6.tree.paths.LowestCommonAncestorPath;
import ru.mifi.practice.vol6.tree.paths.MergePath;
import ru.mifi.practice.vol6.tree.visitors.Distance;
import ru.mifi.practice.vol6.tree.visitors.EulerPath;
import ru.mifi.practice.vol6.tree.visitors.OnSubTree;

import java.io.IOException;
import java.util.Comparator;
import java.util.List;

public abstract class Main {
public static void main(String[] args) throws IOException {
Expand All @@ -23,6 +27,22 @@ public static void main(String[] args) throws IOException {
tree.visit(on, new VisitorStrategy.PreOrder<>());
System.out.println("TIMED: ");
System.out.println(on);
Distance<Integer> distance = new Distance<>();
tree.visit(distance, new VisitorStrategy.PreOrder<>());
System.out.print("DIST : ");
System.out.println(distance.distances());
MergePath<Integer> merge = new MergePath<>();
List<Node<Integer>> path = merge.path(tree, 4, 7);
System.out.print("PATH1: ");
System.out.println(path);
LowestCommonAncestorPath<Integer> lcap = new LowestCommonAncestorPath<>();
path = lcap.path(tree, 4, 7);
System.out.print("PATH2: ");
System.out.println(path);
Diameter<Integer> diameter = new Diameter<>();
path = diameter.path(tree);
System.out.print("DIAM : ");
System.out.println(path);
EulerPath<Integer> euler = new EulerPath<>();
System.out.print("EULER: ");
tree.visit(euler, new VisitorStrategy.PreOrder<>());
Expand Down
50 changes: 50 additions & 0 deletions vol6/src/main/java/ru/mifi/practice/vol6/tree/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,23 @@

import lombok.EqualsAndHashCode;

import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public interface Node<T> extends Visitor.Visit<T> {
static <T> Node<T> root(T value) {
return new Default<>(null, value);
}

Node<T> parent();

Node<T> search(T element);

List<Node<T>> path(T element);

T value();

Node<T> left();
Expand Down Expand Up @@ -37,6 +49,44 @@ private Default(Node<T> parent, T value) {
this.parent = parent;
}

@Override
public Node<T> parent() {
return parent;
}

@Override
public Node<T> search(T element) {
Queue<Node<T>> queue = new LinkedList<>();
queue.add(this);
while (!queue.isEmpty()) {
Node<T> node = queue.poll();
if (node.value() != null && node.value().equals(element)) {
return node;
}
if (node.left() != null) {
queue.add(node.left());
}
if (node.right() != null) {
queue.add(node.right());
}
}
return null;
}

@Override
public List<Node<T>> path(T element) {
Deque<Node<T>> path = new LinkedList<>();
Node<T> it = search(element);
while (it != null) {
path.push(it);
if (it == this) {
break;
}
it = it.parent();
}
return new ArrayList<>(path);
}

@Override
public T value() {
return value;
Expand Down
7 changes: 7 additions & 0 deletions vol6/src/main/java/ru/mifi/practice/vol6/tree/Path.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package ru.mifi.practice.vol6.tree;

import java.util.List;

public interface Path<T> {
List<Node<T>> path(Tree<T> tree, T start, T end);
}
30 changes: 8 additions & 22 deletions vol6/src/main/java/ru/mifi/practice/vol6/tree/Tree.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.function.Function;

public interface Tree<T> extends Visitor.Visit<T> {

void add(T element);

Node<T> find(T element);

@Override
void visit(Visitor<T> visitor, VisitorStrategy<T> strategy);

Expand Down Expand Up @@ -59,7 +59,7 @@ public void add(T owner, T left, T right) {
root.left(left);
root.right(right);
} else {
Node<T> find = search(root, owner);
Node<T> find = root.search(owner);
if (find == null) {
throw new IllegalArgumentException("No such element: " + owner);
}
Expand All @@ -68,26 +68,12 @@ public void add(T owner, T left, T right) {
}
}

private Node<T> search(Node<T> root, T element) {
if (root != null) {
Queue<Node<T>> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
Node<T> node = queue.poll();
if (node.value() != null && node.value().equals(element)) {
return node;
}
if (node.left() != null) {
queue.add(node.left());
}
if (node.right() != null) {
queue.add(node.right());
}
}
@Override
public Node<T> find(T element) {
if (root == null) {
return null;
}
return null;
return root.search(element);
}

;
}
}
24 changes: 24 additions & 0 deletions vol6/src/main/java/ru/mifi/practice/vol6/tree/VisitorStrategy.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,33 @@
package ru.mifi.practice.vol6.tree;

import java.util.HashSet;
import java.util.Set;

@FunctionalInterface
public interface VisitorStrategy<T> {
void visit(Node<T> node, Visitor<T> visitor, VisitorStrategy<T> strategy);

final class AlreadyVisited<T> implements VisitorStrategy<T> {
private final VisitorStrategy<T> strategy;
private final Set<Node<T>> visited = new HashSet<>();

public AlreadyVisited(VisitorStrategy<T> strategy) {
this.strategy = strategy;
}

@Override
public void visit(Node<T> node, Visitor<T> visitor, VisitorStrategy<T> strategy) {
if (node == null || visited.contains(node)) {
return;
}
visited.add(node);
visitor.enterNode(node);
strategy.visit(node.left(), visitor, strategy);
strategy.visit(node.right(), visitor, strategy);
visitor.exitNode(node);
}
}

final class PreOrder<T> implements VisitorStrategy<T> {
@Override
public void visit(Node<T> node, Visitor<T> visitor, VisitorStrategy<T> strategy) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package ru.mifi.practice.vol6.tree.paths;

import ru.mifi.practice.vol6.tree.Node;
import ru.mifi.practice.vol6.tree.Path;
import ru.mifi.practice.vol6.tree.Tree;
import ru.mifi.practice.vol6.tree.VisitorStrategy;
import ru.mifi.practice.vol6.tree.visitors.Distance;

import java.util.Collections;
import java.util.List;
import java.util.Map;

public final class LowestCommonAncestorPath<T> implements Path<T> {
@Override
public List<Node<T>> path(Tree<T> tree, T start, T end) {
Distance<T> vDistance = new Distance<>();
tree.visit(vDistance, new VisitorStrategy.PreOrder<>());
Map<Node<T>, Integer> distances = vDistance.distances();
var nStart = tree.find(start);
var nStartIt = nStart;
var nEnd = tree.find(end);
var nEndIt = nEnd;
int hStart = distances.get(nStart);
int hEnd = distances.get(nEnd);
while (hStart != hEnd) {
if (hStart > hEnd) {
nStartIt = nStartIt.parent();
hStart -= 1;
} else {
nEndIt = nEndIt.parent();
hEnd -= 1;
}
}
while (!nStartIt.equals(nEndIt)) {
nStartIt = nStartIt.parent();
nEndIt = nEndIt.parent();
}
var lca = nStartIt;
List<Node<T>> path = lca.path(start);
Collections.reverse(path);
path.remove(path.size() - 1);
path.addAll(lca.path(end));
return path;
}
}
32 changes: 32 additions & 0 deletions vol6/src/main/java/ru/mifi/practice/vol6/tree/paths/MergePath.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package ru.mifi.practice.vol6.tree.paths;

import ru.mifi.practice.vol6.tree.Node;
import ru.mifi.practice.vol6.tree.Path;
import ru.mifi.practice.vol6.tree.Tree;

import java.util.Collections;
import java.util.List;

public final class MergePath<T> implements Path<T> {

@Override
public List<Node<T>> path(Tree<T> tree, T start, T end) {
Node<T> it = tree.find(start);
Node<T> nEnd = it.search(end);
if (nEnd != null) {
return it.path(end);
}
while (it != null) {
List<Node<T>> path = it.path(end);
if (!path.isEmpty()) {
List<Node<T>> result = it.path(start);
Collections.reverse(result);
result.remove(result.size() - 1);
result.addAll(path);
return result;
}
it = it.parent();
}
return List.of();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package ru.mifi.practice.vol6.tree.visitors;

import ru.mifi.practice.vol6.tree.Node;
import ru.mifi.practice.vol6.tree.Visitor;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

public final class Distance<T> implements Visitor<T> {
private final AtomicInteger level = new AtomicInteger(0);
private final Map<Node<T>, Integer> distances = new HashMap<>();

public void resetLevel(int level) {
this.level.set(level);
}

public void clear() {
distances.clear();
resetLevel(0);
}

public Map<Node<T>, Integer> distances() {
return distances;
}

@Override
public void enterNode(Node<T> node) {
int incremented = level.getAndIncrement();
distances.put(node, incremented);
}

@Override
public void exitNode(Node<T> node) {
level.decrementAndGet();
}

@Override
public void empty() {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ public void exitNode(Node<T> node) {
}
}

public int in(Node<T> node) {
return stepsIn.get(node);
}

public int out(Node<T> node) {
return stepsOut.get(node);
}

@SuppressWarnings("checked")
public List<Node<T>> times() {
List<Node<T>> result = new ArrayList<>();
Expand Down
Loading

0 comments on commit d545588

Please sign in to comment.