1、基本概念
1.1 节点的度:节点拥有的子树数量称为节点的度。度为0的节点称为叶节点。不为0称为分支节点
1.2 树的深度:树中节点的最大层次称为树的深度
1.3 有序树:如果树中节点的各个子树从左至右是有次序的且不能互换的,称为有序树,否则为无序树
1.4 森林:m(m>=0)颗互不相交的树的集合
2、二叉树
2.1 特点:
每个节点最多有两颗子树。
左右子树有顺序,不能颠倒
2.2 特殊的二叉树
只有左子树的二叉树称为左斜树
只有右子树的二叉树称为右斜树
满二叉树:每个分支都有左右子树,且所有叶子都在同一层
完全二叉树:如果节点的编号与同样深度的满二叉树的节点的编号完全相同
2.3 树的遍历
深度优先遍历包括前序遍历,中序遍历,后续遍历,以及递归和非递归方式
广度优先遍历为层遍历
先序遍历
中序遍历
后序遍历
层遍历
public class Tree {
public Node root;
class Node{
public int data;
public Node left;
public Node right;
public Node(int data){
this.data = data;
}
}
/**
* 创建完全二叉树
* */
public Node create(Node node, int[] nums, int index){
if (index>=nums.length)
return null;
node = new Node(nums[index]);
node.left = create(node.left, nums, 2*index+1);
node.right = create(node.right, nums, 2*index+2);
return node;
}
/**
* 先序遍历
* */
public void preTrav(Node node) {
if(node == null)
return;
print(node.data);
preTrav(node.left);
preTrav(node.right);
}
/**
* 中序遍历
* */
public void midTrav(Node node) {
if(node == null)
return;
midTrav(node.left);
print(node.data);
midTrav(node.right);
}
/**
* 后序遍历
* */
public void postTrav(Node node) {
if(node == null)
return;
postTrav(node.left);
postTrav(node.right);
print(node.data);
}
/**
* 非递归先序遍历
*
* 利用栈
* 需要先把右子树压栈
* */
public void preTravFor(Node root) {
if(root == null)
return;
Stack<Node> stack = new Stack<Node>();
stack.push(root);
while(!stack.isEmpty()) {
Node tmpNode = stack.pop();
print(tmpNode.data);
if(tmpNode.right != null)
stack.push(tmpNode.right);
if(tmpNode.left != null)
stack.push(tmpNode.left);
}
}
/**
* 非递归中序遍历
* */
public void midTravFor(Node root) {
if(root == null)
return;
Stack<Node> stack = new Stack<Node>();
Node curNode = root;
while (curNode!=null || !stack.isEmpty()) {
//将左子树全部压栈
while (curNode!=null){
stack.push(curNode);
curNode = curNode.left;
}
curNode = stack.pop();
print(curNode.data);
curNode = curNode.right;
}
}
/**
* 非递归后序遍历
* */
public void postTravFor(Node root) {
if(root == null)
return;
Stack<Node> stack = new Stack<>();
Node curNode = root;
Node rightNode=null;
while(curNode!=null || !stack.isEmpty()) {
//将左子树全部压栈
while (curNode != null) {
stack.push(curNode);
curNode = curNode.left;
}
curNode = stack.pop();
//当前结点没有右结点或上一个结点或是当前结点的右结点,则输出当前结点
while (curNode.right==null || curNode.right==rightNode) {
print(curNode.data);
if(stack.isEmpty())
return;
rightNode = curNode;
curNode = stack.pop();
}
stack.push(curNode);
curNode = curNode.right;
}
}
/**
* 层遍历
*
* 利用队列的先进先出
* */
public void storeyTrav(Node root){
if(root == null)
return;
ArrayDeque<Node> queue = new ArrayDeque<Node>();
queue.offer(root);
while(!queue.isEmpty()) {
Node tmpNode = queue.poll();
print(tmpNode.data);
if (tmpNode.left != null)
queue.offer(tmpNode.left);
if(tmpNode.right != null)
queue.offer(tmpNode.right);
}
}
/**
* 二叉树的深度
* */
public int getMaxDepth(Node node){
if(node == null)
return 0;
int left = getMaxDepth(node.left);
int right = getMaxDepth(node.right);
return left>right ? left+1 : right+1;
}
/**
* 求二叉树的最大宽度 非递归
*
* 利用队列,求出每层的节点数
* */
public int getMaxWidthFor(Node root) {
if(root == null)
return 0;
ArrayDeque<Node> queue = new ArrayDeque<Node>();
int maxWidth = 0;
int len = 1;
queue.offer(root);
while(true){
if((len=queue.size()) == 0)
break;
while (len > 0) {
Node tmpNode = queue.poll();
len--;
if(tmpNode.left != null)
queue.offer(tmpNode.left);
if(tmpNode.right != null)
queue.offer(tmpNode.right);
}
maxWidth = maxWidth > queue.size()?maxWidth : queue.size();
}
return maxWidth;
}
/**
* 求二叉树的最大宽度 递归方式
*
* 将每层的节点数递加 放入数组中 再求数组中的最大值
* */
public int info[]=null;
public boolean getMaxWidth(Node node, int depth) {
if (node == null)
return false;
if (info == null)
return false;
info[depth]++;
getMaxWidth(node.left, depth+1);
getMaxWidth(node.right, depth+1);
return true;
}
private void print(int data){
System.out.print(data+" ");
}
}
调用
public static void main(String[] args) {
Tree tree = new Tree();
int data[] = new int[15];
for (int i=0; i<data.length; i++){
data[i] = i+1;
}
tree.root = tree.create(tree.root, data, 0);
System.out.println("递归先序遍历");
tree.preTrav(tree.root);
System.out.println("\n非递归先序遍历");
tree.preTravFor(tree.root);
System.out.println("\n递归中序遍历");
tree.midTrav(tree.root);
System.out.println("\n非递归中序遍历");
tree.midTravFor(tree.root);
System.out.println("\n递归后序遍历");
tree.postTrav(tree.root);
System.out.println("\n非递归后序遍历");
tree.postTravFor(tree.root);
System.out.println("\n层遍历");
tree.storeyTrav(tree.root);
System.out.println("\n二叉树的深度==>"+tree.getMaxDepth(tree.root));
System.out.println("\n二叉树的宽度 遍历==>"+tree.getMaxWidthFor(tree.root));
tree.info = new int[10];
tree.getMaxWidth(tree.root, 0);
int maxWidth = 0;
for(int info : tree.info){
maxWidth = Math.max(info, maxWidth);
}
System.out.println("\n二叉树的宽度 递归==>"+maxWidth);
}
参考:
大话数据结构
代码 http://blog.youkuaiyun.com/fantasy_lin_/article/details/52751559