重要概念
- 完全二叉树——若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
- 满二叉树——除了叶结点外每一个结点都有左右子叶且叶结点都处在最底层的二叉树,。
- 深度——二叉树的层数,就是高度。
性质
- 在二叉树中,第i层的结点总数不超过2^(i-1);
- 深度为h的二叉树最多有2^h-1个结点(h>=1),最少有h个结点;
- 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;
- 具有n个结点的完全二叉树的深度为int(log2n)+1
- 有N个结点的完全二叉树各结点如果用顺序方式存储,则结点之间有如下关系:
- 若 I 为结点编号则 如果I<>1,则其父结点的编号为I/2;
- 如果2*I<=N,则其左儿子(即左子树的根结点)的编号为2*I;若2*I>N,则无左儿子;
- 如果2*I+1<=N,则其右儿子的结点编号为2*I+1;若2*I+1>N,则无右儿子。
- 给定N个节点,能构成h(N)种不同的二叉树。h(N)为卡特兰数的第N项。h(n)=C(n,2*n)/(n+1)。
- 设有i个枝点,I为所有枝点的道路长度总和,J为叶的道路长度总和J=I+2i
各种遍历的递归以及非递归的实现
其实遍历的非递归实现就是将递归使用的函数栈使用数据结构来表示。
package com.xqq.二叉树的各种遍历;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class Test {
public static void main(String[] args) {
Node head = createBiTree();
System.out.print("递归前序遍历: ");
preOrderRecur(head);
System.out.println();
preOrderUnRecur1(head);
preOrderUnRecur2(head);
System.out.print("递归中序遍历: ");
inOrderRecur(head);
System.out.println();
inOrderUnRecur(head);
System.out.print("递归后序遍历: ");
postOrderRecur(head);
System.out.println();
postOrderUnRecur1(head);
postOrderUnRecur2(head);
layerOrderUnRecur(head);
}
/**
* 递归:前序遍历
*/
public static void preOrderRecur(Node head){
if(head != null){
System.out.print(head.value + " ");
preOrderRecur(head.left);
preOrderRecur(head.right);
}
}
/**
* 递归:中序遍历
*/
public static void inOrderRecur(Node head){
if(head != null){
inOrderRecur(head.left);
System.out.print(head.value + " ");
inOrderRecur(head.right);
}
}
/**
* 递归:后序遍历
*/
public static void postOrderRecur(Node head){
if(head != null){
postOrderRecur(head.left);
postOrderRecur(head.right);
System.out.print(head.value + " ");
}
}
/**
* 非递归:先序遍历
*/
public static void preOrderUnRecur1(Node head){
System.out.print("非递归前序遍历1: ");
if(head == null) return ;
Stack<Node> stack = new Stack<Test.Node>();
stack.push(head);
while(!stack.isEmpty()){
head = stack.pop();
System.out.print(head.value + " ");
if(head.right != null){
stack.push(head.right);
}
if(head.left != null){
stack.push(head.left);
}
}
System.out.println();
}
/**
* 非递归:先序遍历实现的第二种方法
*/
public static void preOrderUnRecur2(Node head){
System.out.print("非递归前序遍历2: ");
if(head == null) return ;
Stack<Node> stack = new Stack<Test.Node>();
while(!stack.isEmpty() || head != null){
if(head != null){
System.out.print(head.value + " ");
stack.push(head);
head = head.left;
}else {
head = stack.pop().right;
}
}
System.out.println();
}
/**
* 非递归:中序遍历
*/
public static void inOrderUnRecur(Node head){
System.out.print("非递归中序遍历: ");
if(head == null) return ;
Stack<Node> stack = new Stack<Test.Node>();
while(!stack.isEmpty() || head != null){
if(head != null){
stack.push(head);
head = head.left;
}else {
head = stack.pop();
System.out.print(head.value + " ");
head = head.right;
}
}
System.out.println();
}
/**
* 非递归:后序遍历
*/
public static void postOrderUnRecur1(Node head){
System.out.print("非递归后序遍历1: ");
if(head == null) return ;
Stack<Node> stack = new Stack<Test.Node>();
Node pop = null;
stack.push(head);
while(!stack.isEmpty()){
head = stack.peek();
if(head.left != null && head.left != pop && head.right != pop){
stack.push(head.left);
}else if(head.right != null && head.right != pop){
stack.push(head.right);
}else{
pop = stack.pop();
System.out.print(pop.value + " ");
}
}
System.out.println();
}
/**
* 非递归:后序遍历实现方法2,后序遍历的顺序为左、右、中,
* 那么将中、右、左顺序遍历二叉树将元素压入栈,最后依次弹出。
*/
public static void postOrderUnRecur2(Node head){
System.out.print("非递归后序遍历2: ");
if(head == null) return ;
Stack<Node> stack1 = new Stack<Test.Node>();
Stack<Node> stack2 = new Stack<Test.Node>();
stack1.push(head);
while(!stack1.isEmpty()){
head = stack1.pop();
stack2.push(head);
if(head.left != null){
stack1.push(head.left);
}
if(head.right != null){
stack1.push(head.right);
}
}
while(!stack2.isEmpty()){
System.out.print(stack2.pop().value + " ");
}
System.out.println();
}
/**
* 非递归:层次遍历
*/
public static void layerOrderUnRecur(Node head){
System.out.print("非递归层次遍历: ");
if(head == null) return ;
Queue<Node> queue = new LinkedList<Test.Node>();
queue.offer(head);
while(!queue.isEmpty()){
head = queue.poll();
System.out.print(head.value + " ");
if(head.left != null){
queue.offer(head.left);
}
if(head.right != null){
queue.offer(head.right);
}
}
System.out.println();
}
/**
* 二叉树的创建
*/
public static Node createBiTree(){
Node head = new Node(1);
Node headLeft = new Node(2);
Node headRight = new Node(3);
head.left = headLeft;
head.right = headRight;
Node hll = new Node(4);
Node hlr = new Node(5);
headLeft.left = hll;
headLeft.right = hlr;
Node hrl = new Node(6);
Node hrr = new Node(7);
headRight.left = hrl;
headRight.right = hrr;
return head;
}
public static class Node{
Node left, right;
int value;
public Node(int value){
this.value = value;
}
}
}
运行结果:
递归前序遍历: 1 2 4 5 3 6 7
非递归前序遍历1: 1 2 4 5 3 6 7
非递归前序遍历2: 1 2 4 5 3 6 7
递归中序遍历: 4 2 5 1 6 3 7
非递归中序遍历: 4 2 5 1 6 3 7
递归后序遍历: 4 5 2 6 7 3 1
非递归后序遍历1: 4 5 2 6 7 3 1
非递归后序遍历2: 4 5 2 6 7 3 1
非递归层次遍历: 1 2 3 4 5 6 7