Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
74 views
in Technique[技术] by (71.8m points)

How to add a function that can compare two tree structure in java?

I have created a tree data structure, but I am unable to add two methods that can get me those nodes which are different and those nodes which are same.

The ** ones are those which are similar nodes and the * ones are different nodes.

Tree Structure 1

>23720634 (Root)
**24751368**
**24751324**
**24751324**
**23726962**
**24751382**
**23728776**
**23724832**
**23727632**
**23728875**
**23728813**
*23722966*
**24751324**
**17712706**

Tree Structure 2

>25764379 (Root)
**24751368**
**24751324**
**24751324**
**23726962**
**24751382**
**23728776**
**23724832**
**23727632**
**23728875**
**23728813**
*24742015*
*24763621*
**24751324**
**17712706**

My IMPLEMENTATION OF TREE

import org.jetbrains.annotations.NotNull;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
 * @param <T>
 */
class TreeNode<T> implements Iterable<TreeNode<T>> {

    private final List<TreeNode<T>> elementsIndex;
    public T data;
    public TreeNode<T> parent;
    public List<TreeNode<T>> children;

    /**
     * @param data =--> data type holder
     */
    public TreeNode(T data) {
        this.data = data;
        this.children = new LinkedList<>();
        this.elementsIndex = new LinkedList<>();
        this.elementsIndex.add(this);
    }

    /**
     * @param depth --> tree depth
     * @return Indentation
     */
    private static String createIndent(int depth) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < depth; i++) {
            sb.append('-');
        }
        sb.append(">");
        return sb.toString();
    }

    /**
     * @param <T> ---> tree data type
     * @param node --> tree leaves
     * @param appender --> add tree values
     */
    public static <T> void printTree(TreeNode<T> node, String appender) {
        //System.out.println(appender + node.getData());
        node.getChildren().forEach(each -> printTree(each, appender + appender));
    }

    /**
     * @param child --> tree children
     * @return child
     */
    public TreeNode<T> addChild(TreeNode<T> child) {
        child.setParent(this);
        this.children.add(child);
        return child;
    }

    /**
     * @param children --> tree children
     */
    public void addChildren(List<TreeNode<T>> children) {
        children.forEach(each -> each.setParent(this));
        this.children.addAll(children);
    }

    /**
     * @return data
     */
    public T getData() {
        return data;
    }

    /**
     * @param data --> tree data type
     */
    public void setData(T data) {
        this.data = data;
    }

    /**
     * @return parent
     */
    public TreeNode<T> getParent() {
        return parent;
    }

    /**
     * @param parent --> tree parent
     */
    private void setParent(TreeNode<T> parent) {
        this.parent = parent;
    }

    /**
     * @return children list
     */
    public List<TreeNode<T>> getChildren() {
        return children;
    }

    /**
     * @return parent
     */
    public boolean isRoot() {
        return parent == null;
    }

    /**
     * @return check the size of child
     */
    public boolean isLeaf() {
        return children.size() == 0;
    }

    /**
     * @param child --> tree children
     * @return child node
     */
    public TreeNode<T> addChild(T child) {
        TreeNode<T> childNode = new TreeNode<>(child);
        childNode.parent = this;
        this.children.add(childNode);
        this.registerChildForSearch(childNode);
        return childNode;
    }

    /**
     * @return the depth of the level
     */
    public int getLevel() {
        if (this.isRoot())
            return 0;
        else
            return parent.getLevel() + 1;
    }

    /**
     * @param node --> tree leaves
     */
    private void registerChildForSearch(TreeNode<T> node) {
        elementsIndex.add(node);
        if (parent != null)
            parent.registerChildForSearch(node);
    }

    public void deleteNode() {
        if (parent != null) {
            int index = this.parent.getChildren().indexOf(this);
            this.parent.getChildren().remove(this);
            for (TreeNode<T> each : getChildren()) {
                each.setParent(this.parent);
            }
            this.parent.getChildren().addAll(index, this.getChildren());
        } else {
            deleteRootNode();
        }
        this.getChildren().clear();
    }

    /**
     * @return parent after deleting
     */
    public TreeNode<T> deleteRootNode() {
        if (parent != null) {
            throw new IllegalStateException("deleteRootNode not called on root");
        }
        TreeNode<T> newParent = null;
        if (!getChildren().isEmpty()) {
            newParent = getChildren().get(0);
            newParent.setParent(null);
            getChildren().remove(0);
            for (TreeNode<T> each : getChildren()) {
                each.setParent(newParent);
            }
            newParent.getChildren().addAll(getChildren());
        }
        this.getChildren().clear();
        return newParent;
    }

    /**
     * @return root
     */
    public TreeNode getRoot() {
        if (parent == null) {
            return this;
        }
        return parent.getRoot();
    }

    /**
     * @param cmp --> comparing the tree variable
     * @return finds the element
     */
    public TreeNode<T> findTreeNode(Comparable<T> cmp) {
        for (TreeNode<T> element : this.elementsIndex) {
            T elData = element.data;
            if (cmp.compareTo(elData) == 0)
                return element;
        }

        return null;
    }

    /**
     * @return the root
     */
    @Override
    public String toString() {

        return data != null ? data.toString() : "[data null]";
    }

    /**
     * @return iterator
     */
    @Override
    public @NotNull Iterator<TreeNode<T>> iterator() {
        return new TreeNodeIterator<>(this);
    }

    /**
     * @param treeRoot --> tree root
     * @param data --> tree data type
     * @return the data else null if not found
     */
    public TreeNode<T> search(TreeNode<T> treeRoot, T data) {

        Comparable<T> searchCriteria = treeData -> {
            boolean nodeOk = treeData.equals(data);
            return nodeOk ? 0 : 1;
        };
        return treeRoot.findTreeNode(searchCriteria);
    }

    /**
     * @param treeRoot --> tree root
     * @return the whole tree
     */
    public StringBuilder display(TreeNode<T> treeRoot) {
        StringBuilder print = new StringBuilder();
        print.append('
');
        for (TreeNode<T> node : treeRoot) {
            String indent = createIndent(node.getLevel());
            print.append(indent).append(node.data);
            print.append("
|");
        }
        if (print.length() > 0)
            print.deleteCharAt(print.length() - 1);
        return print;
    }

}

/**
 * @param <T>
 */
class TreeNodeIterator<T> implements Iterator<TreeNode<T>> {

    private final TreeNode<T> treeNode;
    private final Iterator<TreeNode<T>> childrenCurNodeIterator;
    private ProcessStages doNext;
    private TreeNode<T> next;
    private Iterator<TreeNode<T>> childrenSubNodeIterator;

    /**
     * @param treeNode --> tree children
     */
    public TreeNodeIterator(TreeNode<T> treeNode) {
        this.treeNode = treeNode;
        this.doNext = ProcessStages.ProcessParent;
        this.childrenCurNodeIterator = treeNode.children.iterator();
    }

    /**
     * @return true if there is nay element
     */
    @Override
    public boolean hasNext() {

        if (this.doNext == ProcessStages.ProcessParent) {
            this.next = this.treeNode;
            this.doNext = ProcessStages.ProcessChildCurNode;
            return true;
        }

        if (this.doNext == ProcessStages.ProcessChildCurNode) {
            if (childrenCurNodeIterator.hasNext()) {
                TreeNode<T> childDirect = childrenCurNodeIterator.next();
                childrenSubNodeIterator = childDirect.iterator();
                this.doNext = ProcessStages.ProcessChildSubNode;
                return hasNext();
            } else {
                this.doNext = null;
                return false;
            }
        }

        if (this.doNext == ProcessStages.ProcessChildSubNode) {
            if (childrenSubNodeIterator.hasNext()) {
                this.next = childrenSubNodeIterator.next();
                return true;
            } else {
                this.next = null;
                this.doNext = ProcessStages.ProcessChildCurNode;
                return hasNext();
            }
        }

        return false;
    }

    /**
     * @return the next element
     */
    @Override
    public TreeNode<T> next() {
        return this.next;
    }

    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }

    enum ProcessStages {
        ProcessParent,
        ProcessChildCurNode,
        ProcessChildSubNode
    }

}

When I call the method to get the same nodes, the expected result should be:

**24751368**
**24751324**
**24751324**
**23726962**
**24751382**
**23728776**
**23724832**
**23727632**
**23728875**
**23728813**
**24751324**
**17712706**

When I call the method to get the different nodes, then the expected result to be:

Nodes in Structure 1
*23722966*
Nodes in Structure 2
*24742015*
*24763621*
question from:https://stackoverflow.com/questions/66064057/how-to-add-a-function-that-can-compare-two-tree-structure-in-java

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Please show me a better way ??

public static void main(String[] args) throws Exception{
    
    Path p1 = Path.of("23720634", "24751368", "24751324", "24751324", "23726962", "24751382", "23728776", "23724832", "23727632", "23728875", "23728813", "23722966", "24751324", "17712706");
    Path p2 = Path.of("25764379", "24751368", "24751324", "24751324", "23726962", "24751382", "23728776", "23724832", "23727632", "23728875", "23728813", "24742015", "24763621", "24751324", "17712706");
    comprec(p1, p2);
}

private static void comprec(Path p1, Path p2){
    for(int x1 = 1, x2 = 1, t = 0; ; t++){
        try{
            if(p1.getName(x1).equals(p2.getName(x2))){
                System.out.println("Same Nodes: " + p1.getName(x1++));
                x2++;
            }else if(p1.getName(x1).equals(p2.getName(x2 + t))){
                System.out.println("Nodes in Structure 2: " + p2.getName(x2++));
            }else if(p1.getName(x1 + t).equals(p2.getName(x2))){
                System.out.println("Nodes in Structure 1: " + p1.getName(x1++));
            }else if(p1.getName(x1 + t).equals(p2.getName(x2 + t))){
                throw new IllegalArgumentException();
            }else continue;
        }catch(IllegalArgumentException e){
            if(p1.getNameCount() == x1 || p2.getNameCount() == x2){
                for(int i = x1; i < p1.getNameCount(); i++)
                    System.out.println("Nodes in Structure 1: " + p1.getName(i));
                for(int i = x2; i < p2.getNameCount(); i++)
                    System.out.println("Nodes in Structure 2: " + p2.getName(i));
                break;
            }else{
                System.out.println("Nodes in Structure 1: " + p1.getName(x1++));
                System.out.println("Nodes in Structure 2: " + p2.getName(x2++));
            }
        }
        t = -1;
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...