table of Contents
1. Tree
1 Overview
- Unlike the one-to-one linear relationship represented by the linear table, the tree represents the non-linear relationship between more complex data elements .
- Intuitively, the hierarchy tree branch relationship is defined , is to-many relationship
- Tree definitions : tree (Tree) n is a finite set of nodes (n> = 0)
- There is one and only one root (Root)
- When n>1, the remaining nodes can be divided into m (m>0) disjoint finite sets T1, T2,..., Tm, each of which is a tree itself, and is called the root the sub-tree .
The definition of tree itself is a recursive definition, that is, the concept of tree is used in the definition of tree
2. Some basic terms
- Tree node : contains a data element and several branches pointing to its subtree
- Degree : the number of subtrees owned by the node
- The node with degree ** 0 is called leaf **, or ** terminal node **. Of the node is not 0 ** ** referred to as non-terminal nodes or branch nodes
- Root of the subtree of the node, the node is called a child (Child), corresponding to the node is called the child's parent (parent)
- Call each other between a parent of a child with brothers (sibling)
- Node ancestor from the root node to which all nodes on the branch is.
- Any one node in the subtree rooted at some node in the node are called descendants
- Node -level (Level) is defined beginning from the root, the root of the first layer, the second child root layer, so
- The maximum level of the tree is called a node of the tree depth (depth) or the height
Two, binary tree
1 Overview
-
Definition : added constraints on the general tree:
-
Each node up to two sub-tree, binary tree that is not present in greater than 2 nodes
-
Subtree about the order of the points
-
There are 5 forms :
- Full binary tree and complete binary tree (for the lowest level of full binary tree, delete nodes from right to left)
2. Important features
- Binary tree, at most 2i-1 nodes in the i-th layer
- A binary tree of depth k has at most 2k-1 nodes
- Height (or depth) of K a complete binary tree having at least 2k-2 th leaf node
- Nonempty binary tree leaf node points is equal to a degree of 2 number of nodes plus one, namely:
n0 = n2 + 1
N1 of a complete binary tree can only be 0 or 1
- For a binary tree of degree m , the node of degree 1 is n1, the node of degree 2 is n2,..., the number of nodes of degree m is nm, then the number of leaf nodes: n0 **= 1 + n2 ****+ 2n3****+…+ (m-1)nm**
- A complete binary tree with n nodes, with a depth of log2n + 1
- Numbering nature : a complete binary tree with n nodes (its depth is log2n + 1 ), and each node is numbered from top to bottom and from left to right (1~n) then: if i is the number of a node a :
- If i is not equal to 1, then the number of the parent node of a is: ⌊ i/2 ⌋
- If 2i ≤ n , then the left child number of a is 2i ; if ** 2i> n**, then a** has no left child**;
- If ** 2i + 1 ≤ n**, then the right child number of a is ** 2i + 1**; if ** 2i + 1> n**, then a** has no right child**;
Three, the storage structure of the binary tree
1. Sequential storage
- Using an array to store data elements
- From the storage perspective, this sequential storage structure, only for complete binary tree
Because in the worst case, a single tree with a depth of k and only k nodes (there is no node with a degree of 2 in the tree) requires a one-dimensional array of length 2k-1 .
2. Chain storage
- To list the relationship between the form of data storage elements and data elements.
Fourth, the traversal of the binary tree
1. Determine the binary tree by the traversal sequence
- The first sequence and the sequence can be determined
- A subsequent sequence and may be determined (but note sequence after the last of the root , the next is a right subtree root )
- By the hierarchy and sequence can be determined
2. Estimate the binary tree based on the traverse sequence
- Preamble traversal sequence and postorder traversal sequence identical tree: only the root node
- Preamble traversal and inorder traversal same binary tree: all nodes not left subtree (the right branch of the tree single
- Inorder traversal and postorder traversal of the same binary tree: all nodes not right subtree (left single branch of the tree)
- Preamble traversal and postorder traversal of the opposite binary tree: no left subtree right subtree or not ( only one leaf node ) the height of which is equal to the number of nodes
- Preamble traversal and inorder traversal opposite binary tree: all nodes not right subtree (left single branch of the tree)
- Inorder traversal and postorder traversal of the opposite binary tree: all nodes not left subtree (right single branch of the tree)
3. Traverse and build code
- The establishment of a binary tree
- Depth-first traversal (pre-order, middle-order and post-order)
- Breadth first traversal (first order, second order)
/* BitTree.java */
package com.java.tree;
import java.util.LinkedList;
import java.util.Queue;
/**
* Created by Jaco.Young.
* 2018-06-13 18:26
*/
public class BitTree {
//代表由先序和中序唯一确定的树的根结点
private TreeNode root;
/**
* 提供给外部调用的方法
* 字符数组pre表示先序遍历序列,mid表示中序遍历序列
*/
public void build(char[] pre, char[] mid){
//将创建树的根结点赋值给 root
root = buildTree(pre,0, pre.length-1, mid, 0, mid.length-1);
}
/**
* 前提条件,树中不存在重复元素
* 由先序遍历序列和中序遍历序列,构造二叉树的方法
* 我们建树的过程总是将序列不断地分割成左子树、右子树
* lPre、rPre和lMid、rMid,分别就表示要对先序和中序的哪一部分进行建树
*/
private TreeNode buildTree(char[] pre, int lPre, int rPre, char[] mid, int lMid, int rMid){
//在先序遍历序列中,找到当前这棵树的根结点
char root = pre[lPre];
//在中序遍历序列中,根据先序中的根结点来查找在中序中的位置
int rootIndex = getRootIndex(mid, lMid, rMid, root);
//如果没有找到,说明所给的参数异常
if(rootIndex == -1){
throw new IllegalArgumentException("Illegal Argument!");
}
//计算当前这棵树,左右子树的个数
//整个中序序列:[左子树(lMid) root(rootIndex) 右子树(rMid)]
//左子树[lMid,rootIndex-1]
int lNum = rootIndex - lMid; //rootIndex-1 -lMid + 1
//右子树[rootIndex+1,rMid]
int rNum = rMid - rootIndex; //rMid - (rootIndex + 1) + 1
//开始构建当前根结点的左子树和右子树
//先构建左子树
TreeNode lchild; //作为左子树的根结点
//以当前结点为根的树,没有左子树
if(lNum == 0){
lchild = null;
}else{
//当前这个树的左子树,仍然是一棵树,递归构造这棵树的左子树
//设x为当前树先序中左子树最后一个元素的下标,则:x - (lpre + 1) = lNum
//得:x = lPre + lNum
lchild = buildTree(pre, lPre + 1, lPre+lNum, mid, lMid, rootIndex - 1);
}
//构建右子树
TreeNode rchild;
if(rNum == 0){
rchild = null;
}else{
//当前结点的右子树,仍然包含很多节点,需要递归的构造其右子树
rchild = buildTree(pre, lPre + lNum + 1, rPre, mid, rootIndex + 1, rMid);
}
//构造完整的二叉树
return new TreeNode(root,lchild,rchild);
}
//在中序遍历序列中,根据先序中的根结点来查找在中序中的位置
private int getRootIndex(char[] mid, int lMid, int rMid, char root) {
for(int i = lMid; i <= rMid; i++){
if(mid[i] == root){
return i;
}
}
return -1;
}
//二叉树每一个结点的结构
private class TreeNode{
//结点中存储的数据
char item;
//指向左孩子结点
TreeNode lChild;
//指向右孩子结点
TreeNode rChild;
//构造方法,完成初始化
public TreeNode(char item, TreeNode lChild, TreeNode rChild){
this.item = item;
this.lChild = lChild;
this.rChild = rChild;
}
}
//提供三个让外界调用的方法
public void preTraverse() {
preOrder(root);
}
public void midTraverse() {
midOrder(root);
}
public void postTraverse() {
postOrder(root);
}
//先序遍历 DLR
private void preOrder(TreeNode root) {
if( root != null) {
//先访问根节点
System.out.print(root.item + " ");
//递归访问左子树
preOrder(root.lChild);
//递归访问右子树
preOrder(root.rChild);
}
}
//中序遍历 LDR
private void midOrder(TreeNode root) {
if(root != null) {
//递归访问左子树
midOrder(root.lChild);
//访问根
System.out.print(root.item + " ");
//递归访问右子树
midOrder(root.rChild);
}
}
//后续遍历
// LRD
private void postOrder(TreeNode root) {
if(root != null) {
//递归访问左子树
postOrder(root.lChild);
//递归访问右子树
postOrder(root.rChild);
//访问根
System.out.print(root.item + " ");
}
}
//广度优先遍历 BFS
public void BFS() {
//创建一个能放TreeNode对象的队列
Queue<TreeNode> queue = new LinkedList<>();
//将树的根节点入队列
queue.add(root);
//循环执行广度优先遍历
while(!queue.isEmpty()) {
//将当前的队头元素出队列
TreeNode node = queue.remove();
//访问出队列的节点
System.out.print(node.item + " ");
//出队列的节点是否有左孩子,有则将其左孩子入队列
if(node.lChild != null) {
//有左孩子
queue.add(node.lChild);
}
//出队列的节点是否有右孩子,如果右,将其右孩子如队列
if(node.rChild != null) {
queue.add(node.rChild);
}
}
}
}
/* Test.java*/
package com.java.tree;
/**
* 测试类
* Created by Jaco.Young.
* 2018-06-13 20:16
*/
public class Test {
public static void main(String[] args){
//构造先序遍历序列和中序遍历序列
char[] pre = {
'A','B','E', 'K', 'L', 'F', 'D', 'H', 'J'};
char[] mid = {
'K', 'E', 'L', 'B', 'F', 'A', 'H', 'D', 'J'};
BitTree bitTree = new BitTree();
//根据遍历序列构建二叉树
bitTree.build(pre, mid);
//先序遍历
bitTree.preTraverse();
System.out.println();
//中序遍历
bitTree.midTraverse();
System.out.println();
//后序遍历
bitTree.postTraverse();
System.out.println();
//广度优先遍历
bitTree.BFS();
}
}
The running result is:
ABEKLFDHJ
KELBFAHDJ
KLEFBHJDA
ABDEFHJKL