定义:
二叉树(Binary Tree)是n(n≥0)个结点的有限集合,该集合或者为空集,或者由一个根结点和两颗互不相交的,分别称为根结点的左子树和右子树的二叉树组成。
二叉树的定义也采用了递归,听起来有些绕,如果了解了树的结构的话,二叉树也可以定义为:
二叉树是每个结点最多只有两个分支的树结构。
类型:
满二叉树:
在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层,这样的二叉树称为满二叉树。
满二叉树的特点有:
- 叶子只能出现在最下一层。
- 非叶子结点的度一定是2。
- 在同样深度的二叉树中,满二叉树的结点个人最多,叶子树最多。
完全二叉树:
对一棵具有n个结点的二叉树按层序编号,如果编号为i(1≤≤n)的结点与同样深度的满二叉树中编号为i的结点在二叉树中位置完全相同,则这棵二叉树称为完全二叉树。
前序遍历:
前序遍历(DLR,lchild,data,rchild),是二叉树遍历的一种,也叫做先根遍历、先序遍历、前序周游,可记做根左右。前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。
(1)访问根结点。
(2)前序遍历左子树 。
(3)前序遍历右子树 。
package test;
//前序遍历的递归实现与非递归实现
import java.util.Stack;
public class Test
{
public static void main(String[] args)
{
TreeNode[] node = new TreeNode[10];//以数组形式生成一棵完全二叉树
for(int i = 0; i < 10; i++)
{
node[i] = new TreeNode(i);
}
for(int i = 0; i < 10; i++)
{
if(i*2+1 < 10)
node[i].left = node[i*2+1];
if(i*2+2 < 10)
node[i].right = node[i*2+2];
}
preOrderRe(node[0]);
}
public static void preOrderRe(TreeNode biTree)
{//递归实现
System.out.println(biTree.value);
TreeNode leftTree = biTree.left;
if(leftTree != null)
{
preOrderRe(leftTree);
}
TreeNode rightTree = biTree.right;
if(rightTree != null)
{
preOrderRe(rightTree);
}
}
public static void preOrder(TreeNode biTree)
{//非递归实现
Stack<TreeNode> stack = new Stack<TreeNode>();
while(biTree != null || !stack.isEmpty())
{
while(biTree != null)
{
System.out.println(biTree.value);
stack.push(biTree);
biTree = biTree.left;
}
if(!stack.isEmpty())
{
biTree = stack.pop();
biTree = biTree.right;
}
}
}
}
class TreeNode//节点结构
{
int value;
TreeNode left;
TreeNode right;
TreeNode(int value)
{
this.value = value;
}
}
中序遍历:
中序遍历(LDR)是二叉树遍历的一种,也叫做 中根遍历、中序周游。在二叉树中,先左后根再右。巧记:左根右。
中序遍历首先遍历左子树,然后访问根结点,最后遍历右子树
(1)中序遍历左子树
(2)访问根结点
(3)中序遍历右子树
import java.util.Stack;
public class Test
{
public static void main(String[] args)
{
TreeNode[] node = new TreeNode[10];//以数组形式生成一棵完全二叉树
for(int i = 0; i < 10; i++)
{
node[i] = new TreeNode(i);
}
for(int i = 0; i < 10; i++)
{
if(i*2+1 < 10)
node[i].left = node[i*2+1];
if(i*2+2 < 10)
node[i].right = node[i*2+2];
}
midOrderRe(node[0]);
System.out.println();
midOrder(node[0]);
}
public static void midOrderRe(TreeNode biTree)
{//中序遍历递归实现
if(biTree == null)
return;
else
{
midOrderRe(biTree.left);
System.out.println(biTree.value);
midOrderRe(biTree.right);
}
}
public static void midOrder(TreeNode biTree)
{//中序遍历费递归实现
Stack<TreeNode> stack = new Stack<TreeNode>();
while(biTree != null || !stack.isEmpty())
{
while(biTree != null)
{
stack.push(biTree);
biTree = biTree.left;
}
if(!stack.isEmpty())
{
biTree = stack.pop();
System.out.println(biTree.value);
biTree = biTree.right;
}
}
}
}
class TreeNode//节点结构
{
int value;
TreeNode left;
TreeNode right;
TreeNode(int value)
{
this.value = value;
}
}
后序遍历:
后序遍历(LRD)是二叉树遍历的一种,也叫做 后根遍历、后序周游,可记做左右根。后序遍历有 递归和非递归算法两种。在二叉树中,先左后右再根。
(1)后序遍历左子树
(2)后序遍历右子树
(3)访问根结点
import java.util.Stack;
public class Test
{
public static void main(String[] args)
{
TreeNode[] node = new TreeNode[10];//以数组形式生成一棵完全二叉树
for(int i = 0; i < 10; i++)
{
node[i] = new TreeNode(i);
}
for(int i = 0; i < 10; i++)
{
if(i*2+1 < 10)
node[i].left = node[i*2+1];
if(i*2+2 < 10)
node[i].right = node[i*2+2];
}
postOrderRe(node[0]);
System.out.println("***");
postOrder(node[0]);
}
public static void postOrderRe(TreeNode biTree)
{//后序遍历递归实现
if(biTree == null)
return;
else
{
postOrderRe(biTree.left);
postOrderRe(biTree.right);
System.out.println(biTree.value);
}
}
public static void postOrder(TreeNode biTree)
{//后序遍历非递归实现
int left = 1;//在辅助栈里表示左节点
int right = 2;//在辅助栈里表示右节点
Stack<TreeNode> stack = new Stack<TreeNode>();
Stack<Integer> stack2 = new Stack<Integer>();//辅助栈,用来判断子节点返回父节点时处于左节点还是右节点。
while(biTree != null || !stack.empty())
{
while(biTree != null)
{//将节点压入栈1,并在栈2将节点标记为左节点
stack.push(biTree);
stack2.push(left);
biTree = biTree.left;
}
while(!stack.empty() && stack2.peek() == right)
{//如果是从右子节点返回父节点,则任务完成,将两个栈的栈顶弹出
stack2.pop();
System.out.println(stack.pop().value);
}
if(!stack.empty() && stack2.peek() == left)
{//如果是从左子节点返回父节点,则将标记改为右子节点
stack2.pop();
stack2.push(right);
biTree = stack.peek().right;
}
}
}
}
class TreeNode//节点结构
{
int value;
TreeNode left;
TreeNode right;
TreeNode(int value)
{
this.value = value;
}
}