Tree structure and Java implementation

Keywords: Java Windows git Spring

Tree structure and Java implementation

Catalog
Preface
When referring to the data structure "tree", I believe that many people think of "binary tree" first.

Indeed, as an important data structure, binary tree combines the advantages of arrays and chained lists and has many important applications.

As we all know, arrays are characterized by fast queries and fast positioning of an element based on index.However, if you want to insert an element, you need to move all the elements that follow its position back.On average, an ordered array with a length of N has N/2 of the number of elements to be moved by the inserted element.The time complexity of inserting an ordered array is O(N), and the time complexity of deleting operations is O(N).

Ordered arrays are not recommended for frequently inserted and deleted data.

The insertion and deletion of chained lists are efficient, as long as the reference of some values is changed, the time complexity is O(1).However, the query efficiency of the chain table is very low. Every time you start from scratch, you access each data item of the chain table in turn.On average, to query an element from a chain table with N elements, traverse N/2 elements with O(N) time complexity

Chain lists are not recommended for frequently searched data.

Instead of describing binary trees, this section begins with a description of tree as a data structure.I believe that with the knowledge in this section as the basis, it will be much easier to learn about binary trees.

The concept of trees

Summary
In computer science, a tree is an abstract data type (ADT) or a data structure that implements this abstract data type to simulate data collections that have a tree structure.

It is a set of n (n>0) finite nodes with hierarchical relationship.

It is called a tree because it looks like an upside-down tree, that is, it has roots facing up and leaves facing down.

It has the following characteristics:

Each node has only a limited number of children or no children; nodes without a parent node are called root nodes; each non-root node has and has only one parent node; each child node can be divided into several disjoint subtrees except the root node; there is no cycle in the tree - Wikipedia

By definition, the following structure is not a tree:

term

Route
The path between these two nodes is the path through which all the nodes from one node to another pass in turn.

root
A node at the top of a tree is called a root.There is only one path from the root to any node.

Parent Node**
Except for the root node, each node can find a unique node up, which is the parent of the current node.Correspondingly, the child node is below the parent node.

Leaf Node
A rod commander without a child node is called a leaf node.

subtree
The tree where each child node is the root node is a subtree.

layer
The algebra of a tree structure is the layer of the tree.

degree
The degree of the largest node in a tree is called the degree of the tree.

Brother Node
Nodes with the same parent node are called sibling nodes to each other.

Practical Application**
Tree structure has a very wide range of applications, such as our common file directory system, which is a tree structure.

For example, on the CMD command line of the Windows10 operating system, you can output a directory tree by typing the tree command:

tree
//Folder PATH List for Volume Windows
//Volume serial number is 1CEB-7ABE
C:.
├─blog
│  ├─cache
│  │  └─JavaCacheGuidance
│  ├─datastructure
│  ├─editor
│  │  └─notepad++
│  ├─framework
│  │  └─guava
│  │      └─retry
│  ├─git
│  └─java
│      └─package-info
├─category
│  ├─food
│  │  ├─fruit
│  │  └─self
│  ├─job
│  │  └─bz
│  │      └─project
│  │          └─ad
│  │              └─exch
│  ├─people
│  ├─practical
│  │  └─work
│  │      └─ecommerce
│  │          └─inventory
│  ├─tech
│  │  ├─algorithm
│  │  │  └─tree
│  │  └─java
│  │      ├─concurrent
│  │      │  └─thread
│  │      ├─design
│  │      ├─i18n
│  │      ├─jcf
│  │      └─spring
│  │          └─springboot
│  └─tool
│      ├─data
│      │  └─db
│      │      ├─mysql
│      │      └─redis
│      └─site
│          └─stackoverflow
└─me
    └─phonephoto

Implementation Tree
After explaining the characteristics and related concepts of the tree structure, the basic operation of the tree structure is implemented in Java, and the operations of creating the tree, adding child nodes, traversing the tree, and searching for specified nodes are demonstrated.

TreeNode

package net.ijiangtao.tech.algorithms.algorithmall.datastructure.tree;

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

/**
 * Implement tree structure
 *
 * @author ijiangtao
 * @create 2019-04-18 15:13
 **/
public class TreeNode<T> implements Iterable<TreeNode<T>> {

    /**
     * Tree Node
     */
    public T data;

    /**
     * Parent node, root has no parent node
     */
    public TreeNode<T> parent;

    /**
     * Child node, leaf node has no child node
     */
    public List<TreeNode<T>> children;

    /**
     * Save the current node and all its children for easy query
     */
    private List<TreeNode<T>> elementsIndex;

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

    /**
     * Determine if root: root has no parent node
     *
     * @return
     */
    public boolean isRoot() {
        return parent == null;
    }

    /**
     * Determine whether it is a leaf node: child nodes have no children
     *
     * @return
     */
    public boolean isLeaf() {
        return children.size() == 0;
    }

    /**
     * Add a child node
     *
     * @param child
     * @return
     */
    public TreeNode<T> addChild(T child) {
        TreeNode<T> childNode = new TreeNode<T>(child);

        childNode.parent = this;

        this.children.add(childNode);

        this.registerChildForSearch(childNode);

        return childNode;
    }

    /**
     * Get the layer of the current node
     *
     * @return
     */
    public int getLevel() {
        if (this.isRoot()) {
            return 0;
        } else {
            return parent.getLevel() + 1;
        }
    }

    /**
     * Recursively add a new node to the current node and all parent nodes of the current node
     *
     * @param node
     */
    private void registerChildForSearch(TreeNode<T> node) {
        elementsIndex.add(node);
        if (parent != null) {
            parent.registerChildForSearch(node);
        }
    }

    /**
     * Search for a node from the current node and all its children
     *
     * @param cmp
     * @return
     */
    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;
    }

    /**
     * Get the iterator for the current node
     *
     * @return
     */
    @Override
    public Iterator<TreeNode<T>> iterator() {
        TreeNodeIterator<T> iterator = new TreeNodeIterator<T>(this);
        return iterator;
    }

    @Override
    public String toString() {
        return data != null ? data.toString() : "[tree data null]";
    }

}

TreeNodeIterator

package net.ijiangtao.tech.algorithms.algorithmall.datastructure.tree;

import java.util.Iterator;

/**
 *
 * iterator
 *
 * @author ijiangtao
 * @create 2019-04-18 15:24
 **/
public class TreeNodeIterator<T> implements Iterator<TreeNode<T>> {

    enum ProcessStages {
        ProcessParent, ProcessChildCurNode, ProcessChildSubNode
    }

    private ProcessStages doNext;

    private TreeNode<T> next;

    private Iterator<TreeNode<T>> childrenCurNodeIter;

    private Iterator<TreeNode<T>> childrenSubNodeIter;

    private TreeNode<T> treeNode;

    public TreeNodeIterator(TreeNode<T> treeNode) {
        this.treeNode = treeNode;
        this.doNext = ProcessStages.ProcessParent;
        this.childrenCurNodeIter = treeNode.children.iterator();
    }

    @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 (childrenCurNodeIter.hasNext()) {
                TreeNode<T> childDirect = childrenCurNodeIter.next();
                childrenSubNodeIter = childDirect.iterator();
                this.doNext = ProcessStages.ProcessChildSubNode;
                return hasNext();
            } else {
                this.doNext = null;
                return false;
            }
        }

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

        return false;
    }

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

    /**
     * Deleting nodes is not currently supported
     */
    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }

}

test
The tree structure implemented below is identical to that in the previous diagram.
package net.ijiangtao.tech.algorithms.algorithmall.datastructure.tree;

/**

  • tree

*

  • @author ijiangtao
  • @create 2019-04-18 15:03

**/
public class TreeDemo1 {

public static void main(String[] args) {

    System.out.println("********************Test traversal*************************");

    TreeNode<String> treeRoot = getSetA();
    for (TreeNode<String> node : treeRoot) {
        String indent = createIndent(node.getLevel());
        System.out.println(indent + node.data);
    }

    System.out.println("********************Test Search*************************");

    Comparable<String> searchFCriteria = new Comparable<String>() {
        @Override
        public int compareTo(String treeData) {
            if (treeData == null)
                return 1;
            boolean nodeOk = treeData.contains("F");
            return nodeOk ? 0 : 1;
        }
    };
    TreeNode<String> foundF = treeRoot.findTreeNode(searchFCriteria);
    System.out.println("F: parent=" + foundF.parent + ",children=" + foundF.children);

}

private static String createIndent(int depth) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < depth; i++) {
        sb.append(' ');
    }
    return sb.toString();
}

public static TreeNode<String> getSetA() {

    TreeNode<String> A = new TreeNode<String>("A");
    {
        TreeNode<String> B = A.addChild("B");
        TreeNode<String> C = A.addChild("C");
        TreeNode<String> D = A.addChild("D");
        {
            TreeNode<String> E = B.addChild("E");
            TreeNode<String> F = C.addChild("F");
            TreeNode<String> G = C.addChild("G");
            {
                TreeNode<String> H = F.addChild("H");
                TreeNode<String> I = F.addChild("I");
                TreeNode<String> J = F.addChild("J");
            }
        }
    }

    return A;
}

}
output

********************Test traversal*************************
A
 B
  E
 C
  F
   H
   I
   J
  G
 D
********************Test Search*************************
F: parent=C,children=[H, I, J]

summary
In this section, I lead you to understand tree, an important data structure, and explain the concepts and terminology related to tree. Finally, I implement the basic tree operation for you.

Having studied this section will help with the binary trees we'll cover below, as well as the source code for TreeSet and TreeMap in Java.

Posted by Mikemcs on Wed, 15 May 2019 01:46:27 -0700