From the beginning of a good school [04] data structure programmers today in your heart there is no point "tree" it?

Earlier we were talking about linear table structure, stacks, queues, and so on. Today we are talking about a non-linear table structure tree. This tree data structure than the linear form of the data structure is much more complex, the content will be more, we start with the first tree (Tree) start with.
@

Tree (Tree)

Tree structure is a nonlinear structure, presenting data elements between its branches, delamination characteristics.

1. Definition of the tree

Tree (Tree) T is a finite set consisting of n (n≥0) nodes, when n = 0, T is referred to empty tree; otherwise, any non-empty tree T:
(1) one and only one a particular node, it is no predecessor nodes, referred to as the root (root) nodes;
(2) the remaining nodes can be divided into m (m≥0) disjoint subsets T1, T2, ... , Tm, wherein each subset is itself a tree, calling it subtree (subtree) as the root.

Note: The definition of a recursive tree , the "Tree tree there." Recursive definition tree revealed the inherent characteristics of the tree

2. What is a tree structure

What is a "tree"? Better definition, are not illustrated to intuitive. So I drew trees "tree" in the figure. You look at these "trees" have what characteristics?
Here Insert Picture Description
Have you ever noticed, "tree" structure of this data we really like in real life "tree"

3. Why use a tree structure

In an ordered array, you can quickly find a specific value, but want to insert a new data item in an ordered array, you must first find the new data item into position, and then the new data item larger than the data items to after a move to make room for new data entry, delete the same token, such a move is very time-consuming. Obviously, if to do a lot of insert and delete and delete operations, not the choice of an ordered array. On the other hand, the list can quickly add and delete a data item, but to find items in the list is not easy, it is necessary to start from scratch each data item to access the list until you find the data item, this process is very slow. This tree data structure, not only as fast as the list insertions and deletions, but also want to find as quickly ordered array

Common tree 4. The term

Junction - contains a plurality of data elements and their sub-branches of the tree point
of - node has a number of sub-tree
of the tree - the tree nodes in the maximum degree of
leaf - is zero node
branch node (non-terminal nodes) - node is not zero degree
child and parent - child tree node is called a child of the root node, and accordingly, the parent node is called a child
brothers - - a parent of a child with
ancestors and descendants - all nodes on the branch through from the root to the node. Accordingly, any one of the nodes in the subtree rooted at a node is referred to as the node's descendants.
Level nodes - nodes begin to define the root level, the root node level 1, the level of its child nodes 2, ......
cousins - the parent node in the same layer of the
depth of the tree - maximum tree node hierarchy
ordered and unordered tree tree - if the sub-tree of the tree, each node has a left to right as a sequence (i.e., a position not interchangeable), the tree is called ordered tree; otherwise known disorder tree.
Limited set of forest --m (m≥0) trees disjoint tree

Here Insert Picture Description
Here, the tree will talk about, talk about the next binary tree (Binary Tree)

Binary Tree (Binary Tree)

Tree structure varied, but the most commonly used is a binary tree, usually the most common tree is the binary tree. Each node binary tree has at most two children, were left child and the right child node. Binary tree, there are two special trees, and are full binary tree complete binary tree. Full binary tree is a complete binary tree is a special case.

1. Definition and characteristics of binary tree

二叉树的定义:
二叉树(Binary Tree)是n(n≥0)个结点的有限集合BT,它或者是空集,或者由一个根结点和两棵分别称为左子树和右子树的互不相交的二叉树组成 。
————————————
二叉树的特点:
每个结点至多有二棵子树(即不存在度大于2的结点);二叉树的子树有左、右之分,且其次序不能任意颠倒。

2.几种特殊形式的二叉树

1、满二叉树
定义:深度为k且有2k-1个结点的二叉树,称为满二叉树。
特点:每一层上的结点数都是最大结点数
2、完全二叉树
定义:
深度为k,有n个结点的二叉树当且仅当其每一个结点都与深度为k的满二叉树中编号从1至n的结点一一对应时,称为完全二叉树
特点:
特点一 : 叶子结点只可能在层次最大的两层上出现;
特点二 : 对任一结点,若其右分支下子孙的最大层次为l,则其左分支下子孙的最大层次必为l 或l+1

建议看图对应文字综合理解

Here Insert Picture Description
代码创建二叉树

首先,创建一个节点Node类

package demo5;
/*
 * 节(结)点类 
 */
public class Node {
    //节点的权
    int value;
    //左儿子(左节点)
    Node leftNode;
    //右儿子(右节点)
    Node rightNode;
    //构造函数,初始化的时候就给二叉树赋上权值
    public Node(int value) {
        this.value=value;
    }
    
    //设置左儿子(左节点)
    public void setLeftNode(Node leftNode) {
        this.leftNode = leftNode;
    }
    //设置右儿子(右节点)
    public void setRightNode(Node rightNode) {
        this.rightNode = rightNode;
    }

接着创建一个二叉树BinaryTree 类

package demo5;
/*
 * 二叉树Class
 */
public class BinaryTree {
    //根节点root
    Node root;
    
    //设置根节点
    public void setRoot(Node root) {
        this.root = root;
    }
    
    //获取根节点
    public Node getRoot() {
        return root;
    }
}

最后创建TestBinaryTree 类(该类主要是main方法用来测试)来创建一个二叉树

package demo5;
public class TestBinaryTree {

    public static void main(String[] args) {
        //创建一颗树
        BinaryTree binTree = new BinaryTree();
        //创建一个根节点
        Node root = new Node(1);
        //把根节点赋给树
        binTree.setRoot(root);
        //创建一个左节点
        Node rootL = new Node(2);
        //把新创建的节点设置为根节点的子节点
        root.setLeftNode(rootL);
        //创建一个右节点
        Node rootR = new Node(3);
        //把新创建的节点设置为根节点的子节点
        root.setRightNode(rootR);
        //为第二层的左节点创建两个子节点
        rootL.setLeftNode(new Node(4));
        rootL.setRightNode(new Node(5));
        //为第二层的右节点创建两个子节点
        rootR.setLeftNode(new Node(6));
        rootR.setRightNode(new Node(7));
    }

}

下面将会讲的遍历、查找节点、删除节点都将围绕这三个类开展

不难看出创建好的二叉树如下(画的不好,还望各位见谅):
Here Insert Picture Description

3.二叉树的两种存储方式

二叉树既可以用链式存储,也可以用数组顺序存储。数组顺序存储的方式比较适合完全二叉树,其他类型的二叉树用数组存储会比较浪费存储空间,所以链式存储更合适。

我们先来看比较简单、直观的链式存储法
Here Insert Picture Description
接着是基于数组的顺序存储法(该例子是一棵完全二叉树)
Here Insert Picture Description
上面例子是一棵完全二叉树,所以仅仅“浪费”了一个下标为0的存储位置。如果是非完全二叉树,则会浪费比较多的数组存储空间,如下。
Here Insert Picture Description
Here Insert Picture Description
还记得堆和堆排序吗,堆其实就是一种完全二叉树,最常用的存储方式就是数组。

4.二叉树的遍历

前面我讲了二叉树的基本定义和存储方法,现在我们来看二叉树中非常重要的操作,二叉树的遍历。这也是非常常见的面试题。

经典遍历的方法有三种,前序遍历中序遍历后序遍历

前序遍历是指,对于树中的任意节点来说,先打印这个节点,然后再打印它的左子树,最后打印它的右子树。

中序遍历是指,对于树中的任意节点来说,先打印它的左子树,然后再打印它本身,最后打印它的右子树。

后序遍历是指,对于树中的任意节点来说,先打印它的左子树,然后再打印它的右子树,最后打印这个节点本身。

Here Insert Picture Description
我想,睿智的你已经想到了二叉树的前、中、后序遍历就是一个递归的过程。比如,前序遍历,其实就是先打印根节点,然后再递归地打印左子树,最后递归地打印右子树。

在之前创建好的二叉树代码之上,我们来使用这三种方法遍历一下~

依旧是在Node节点类上添加方法:可以看出遍历方法都是用的递归思想

package demo5;
/*
 * 节(结)点类 
 */
public class Node {
//===================================开始 遍历========================================
    //前序遍历
    public void frontShow() {
        //先遍历当前节点的内容
        System.out.println(value);
        //左节点
        if(leftNode!=null) {
            leftNode.frontShow();
        }
        //右节点
        if(rightNode!=null) {
            rightNode.frontShow();
        }
    }

    //中序遍历
    public void midShow() {
        //左子节点
        if(leftNode!=null) {
            leftNode.midShow();
        }
        //当前节点
        System.out.println(value);
        //右子节点
        if(rightNode!=null) {
            rightNode.midShow();
        }
    }

    //后序遍历
    public void afterShow() {
        //左子节点
        if(leftNode!=null) {
            leftNode.afterShow();
        }
        //右子节点
        if(rightNode!=null) {
            rightNode.afterShow();
        }
        //当前节点
        System.out.println(value);
    }

}

然后依旧是在二叉树BinaryTree 类上添加方法,并且添加的方法调用Node类中的遍历方法

package demo5;
/*
 * 二叉树Class
 */
public class BinaryTree {

    public void frontShow() {
        if(root!=null) {
            //调用节点类Node中的前序遍历frontShow()方法
            root.frontShow();
        }
    }

    public void midShow() {
        if(root!=null) {
            //调用节点类Node中的中序遍历midShow()方法
            root.midShow();
        }
    }

    public void afterShow() {
        if(root!=null) {
            //调用节点类Node中的后序遍历afterShow()方法
            root.afterShow();
        }
    }

}

依旧是在TestBinaryTree类中测试

package demo5;

public class TestBinaryTree {

    public static void main(String[] args) {
        //前序遍历树
        binTree.frontShow();
        System.out.println("===============");
        //中序遍历
        binTree.midShow();
        System.out.println("===============");
        //后序遍历
        binTree.afterShow();
        System.out.println("===============");
        //前序查找
        Node result = binTree.frontSearch(5);
        System.out.println(result);
        
}

如果递归理解的不是很透,我可以分享一个学习的小方法:我建议各位可以这样断点调试,一步一步调,思维跟上,仔细推敲每一步的运行相信我,你会重新认识到递归!(像下面这样贴个图再一步一步断点思维更加清晰)
Here Insert Picture Description
贴一下我断点对递归的分析,希望对你有一定的帮助~
Here Insert Picture Description
二叉树遍历的递归实现思路自然、简单,易于理解,但执行效率较低。为了提高程序的执行效率,可以显式的设置栈,写出相应的非递归遍历算法。非递归的遍历算法可以根据递归算法的执行过程写出。至于代码可以尝试去写一写,这也是一种提升!具体的非递归算法主要流程图贴在下面了:
Here Insert Picture Description
二叉树遍历算法分析:

二叉树遍历算法中的基本操作是访问根结点,不论按哪种次序遍历,都要访问所有的结点,对含n个结点的二叉树,其时间复杂度均为O(n)。所需辅助空间为遍历过程中所需的栈空间,最多等于二叉树的深度k乘以每个结点所需空间数,最坏情况下树的深度为结点的个数n,因此,其空间复杂度也为O(n)。

5.二叉树中节点的查找与删除

刚才讲到二叉树的三种金典遍历放法,那么节点的查找同样是可以效仿的,分别叫做前序查找、中序查找以及后序查找,下面代码只以前序查找为例,三者查找方法思路类似~

至于删除节点,有三种情况:

1、如果删除的是根节点,那么二叉树就完全被删了
2、如果删除的是双亲节点,那么该双亲节点以及他下面的所有子节点所构成的子树将被删除
3、如果删除的是叶子节点,那么就直接删除该叶子节点

那么,我把完整的三个类给贴出来(包含创建、遍历、查找、删除)

依旧是Node节点类

package demo5;
/*
 * 节(结)点类 
 */
public class Node {
    //节点的权
    int value;
    //左儿子
    Node leftNode;
    //右儿子
    Node rightNode;
    //构造函数,初始化的时候就给二叉树赋上权值
    public Node(int value) {
        this.value=value;
    }
    
    //设置左儿子
    public void setLeftNode(Node leftNode) {
        this.leftNode = leftNode;
    }
    //设置右儿子
    public void setRightNode(Node rightNode) {
        this.rightNode = rightNode;
    }
    
    //前序遍历
    public void frontShow() {
        //先遍历当前节点的内容
        System.out.println(value);
        //左节点
        if(leftNode!=null) {
            leftNode.frontShow();
        }
        //右节点
        if(rightNode!=null) {
            rightNode.frontShow();
        }
    }

    //中序遍历
    public void midShow() {
        //左子节点
        if(leftNode!=null) {
            leftNode.midShow();
        }
        //当前节点
        System.out.println(value);
        //右子节点
        if(rightNode!=null) {
            rightNode.midShow();
        }
    }

    //后序遍历
    public void afterShow() {
        //左子节点
        if(leftNode!=null) {
            leftNode.afterShow();
        }
        //右子节点
        if(rightNode!=null) {
            rightNode.afterShow();
        }
        //当前节点
        System.out.println(value);
    }

    //前序查找
    public Node frontSearch(int i) {
        Node target=null;
        //对比当前节点的值
        if(this.value==i) {
            return this;
        //当前节点的值不是要查找的节点
        }else {
            //查找左儿子
            if(leftNode!=null) {
                //有可能可以查到,也可以查不到,查不到的话,target还是一个null
                target = leftNode.frontSearch(i);
            }
            //如果不为空,说明在左儿子中已经找到
            if(target!=null) {
                return target;
            }
            //查找右儿子
            if(rightNode!=null) {
                target=rightNode.frontSearch(i);
            }
        }
        return target;
    }
    
    //删除一个子树
    public void delete(int i) {
        Node parent = this;
        //判断左儿子
        if(parent.leftNode!=null&&parent.leftNode.value==i) {
            parent.leftNode=null;
            return;
        }
        //判断右儿子
        if(parent.rightNode!=null&&parent.rightNode.value==i) {
            parent.rightNode=null;
            return;
        }
        
        //递归检查并删除左儿子
        parent=leftNode;
        if(parent!=null) {
            parent.delete(i);
        }
        
        //递归检查并删除右儿子
        parent=rightNode;
        if(parent!=null) {
            parent.delete(i);
        }
    }

}

依旧是BinaryTree 二叉树类

package demo5;
/*
 * 二叉树Class
 */
public class BinaryTree {
    //根节点root
    Node root;
    
    //设置根节点
    public void setRoot(Node root) {
        this.root = root;
    }
    
    //获取根节点
    public Node getRoot() {
        return root;
    }

    public void frontShow() {
        if(root!=null) {
            //调用节点类Node中的前序遍历frontShow()方法
            root.frontShow();
        }
    }

    public void midShow() {
        if(root!=null) {
            //调用节点类Node中的中序遍历midShow()方法
            root.midShow();
        }
    }

    public void afterShow() {
        if(root!=null) {
            //调用节点类Node中的后序遍历afterShow()方法
            root.afterShow();
        }
    }
    //查找节点i
    public Node frontSearch(int i) {
        return root.frontSearch(i);
    }
    //删除节点i
    public void delete(int i) {
        if(root.value==i) {
            root=null;
        }else {
            root.delete(i);
        }
    }
    
}

Still TestBinaryTree test class

package demo5;

public class TestBinaryTree {

    public static void main(String[] args) {
        //创建一颗树
        BinaryTree binTree = new BinaryTree();
        //创建一个根节点
        Node root = new Node(1);
        //把根节点赋给树
        binTree.setRoot(root);
        //创建一个左节点
        Node rootL = new Node(2);
        //把新创建的节点设置为根节点的子节点
        root.setLeftNode(rootL);
        //创建一个右节点
        Node rootR = new Node(3);
        //把新创建的节点设置为根节点的子节点
        root.setRightNode(rootR);
        //为第二层的左节点创建两个子节点
        rootL.setLeftNode(new Node(4));
        rootL.setRightNode(new Node(5));
        //为第二层的右节点创建两个子节点
        rootR.setLeftNode(new Node(6));
        rootR.setRightNode(new Node(7));
        //前序遍历树
        binTree.frontShow();
        System.out.println("===============");
        //中序遍历
        binTree.midShow();
        System.out.println("===============");
        //后序遍历
        binTree.afterShow();
        System.out.println("===============");
        //前序查找
        Node result = binTree.frontSearch(5);
        System.out.println(result);
        
        System.out.println("===============");
        //删除一个子树
        binTree.delete(4);
        binTree.frontShow();
        
    }

}

Here, to sum up, we learn a non-linear table data structures, trees. About the tree, there are several commonly used concepts you need to know, that is: the root, the height of the leaf node, the parent node, child node, sibling, as well as nodes, depth, layers, and the height of the tree and so on. Usually the most common tree is the binary tree. Each node binary tree has at most two children , were left child and the right child node. Binary tree, there are two special trees, and are full binary tree complete binary tree. Full binary tree complete binary tree is a special case . Binary tree may be stored with the chain, it may be stored in an array sequence. Storage array in a sequential manner more suitable for complete binary tree, binary tree with an array of other types of storage would be more a waste of storage space. In addition, a binary tree in a very important operation that is before, during and after the operation order traversal , traversing the time complexity is O (n), you need to understand and use recursive code to implement.

If this article helpful, even a little bit, please choose a chant praise to you, thank you ~

I welcome you to focus on the public number, to explore technology, yearning technology, the pursuit of technology ... is coming to say good pots Friends Oh ...

Here Insert Picture Description

Guess you like

Origin www.cnblogs.com/yichunguo/p/11895445.html