树的基本概念:
- 结点的度:一个结点含有的子结点的个数称为该结点的度;
- 叶结点或终端结点:度为0的结点称为叶结点;
- 非终端结点或分支结点:度不为0的结点;
- 双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点;
- 孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点;
- 兄弟结点:具有相同父结点的结点互称为兄弟结点;
- 树的度:一棵树中,最大的结点的度称为树的度;
- 结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推;
- 树的高度或深度:树中结点的最大层次;
- 堂兄弟结点:双亲在同一层的结点互为堂兄弟;
- 结点的祖先:从根到该结点所经分支上的所有结点;
- 子孙:以某结点为根的子树中任一结点都称为该结点的子孙。
- 森林:由m(m>=0)棵互不相交的树的集合称为森林;
- 无序树:树中任意节点的子结点之间没有顺序关系,这种树称为无序树,也称为自由树;
- 有序树:树中任意节点的子结点之间有顺序关系,这种树称为有序树;
- 二叉树:每个节点最多含有两个子树的树称为二叉树;
- 完全二叉树:若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树
- 满二叉树:除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树。
- 哈夫曼树:带权路径最短的二叉树称为哈夫曼树或最优二叉树;
树的节点类的定义
public class TreeNode{
//定义数据域
private int val;
//定义左节点
private TreeNode left;
//定义右节点
private TreeNode right;
//定义无参构造函数
public TreeNode(){
}
//定义有参构造函数
public TreeNode(int x){
val = x;
}
//定义值域的输出
@Override
public String toString(){
return "[" + val + "]";
}
}
前序遍历二叉树
public static void PreOrder(TreeNode root){
//递归调用结束条件
if(root == null){
return;
}
//访问根节点数据域
System.out.println(root.val + " ");
//前序递归遍历root的左子树
PreOrder(root.left);
//前序递归遍历root的右子树
PreOrder(root.right);
}
非递归实现前序遍历二叉树
//方法一
public static void PreOeder(TreeNode root){
if(tree == null){
return;
}
//定义栈
Stack<TreeNode> stack = new Stack<>();
//将根节点压入栈中
stack.push(tree);
while(stack != null){
//出栈
TreeNode node = stack.pop();
System.out.println(node.val);
//若右节点不为空,则入栈
if(node.right != null){
stack.push(node.right);
}
//若左节点不为空,则入栈
if(node.left != null){
stack.push(node.left);
}
}
}
//方法二
public static void PreOrder(){
TreeNode node = root;
TreeNode Stack[100];
//顺序栈初始化
int top = - 1;
while(node != null || top != - 1){
while(node != null){
//输出节点对应的值
System.out.println(node.val);
//左节点入队
stack[++top] = node;
node = node.left;
}
//栈非空
if(top != - 1){
//将栈顶元素弹出给node,然后遍历右子树
node = stack[top--];
node = node.right;
}
}
}
中序遍历二叉树
public static void InOrder(TreeNode root){
//递归调用结束条件
if(root == null){
return;
}
//前序递归遍历root的左子树
PreOrder(root.left);
//访问根节点数据域
System.out.println(root.val + " ");
//前序递归遍历root的右子树
PreOrder(root.right);
}
非递归实现中序遍历二叉树
//方法一
public static void InOrder(TreeNode root){
Stack<TreeNode> stack = new Stack<>();
while(root != null || Stack != null){
//将树的左结点入栈
while(root != null){
stack.push(root);
root = root.left;
}
//当栈非空,将树的值输出,然后遍历右节点
if(stack != null){
root = stack.pop();
System.out.println(root.val);
root = root.right;
}
}
}
//方法二
public static void PreOrder(){
TreeNode node = root;
TreeNode Stack[100];
//顺序栈初始化
int top = - 1;
while(node != null || top != - 1){
while(node != null){
//左节点入队
stack[++top] = node;
node = node.left;
}
//栈非空
if(top != - 1){
//将栈顶元素弹出给node,然后遍历右子树
node = stack[top--];
node = node.right;
}
//输出节点对应的值
System.out.println(node.val);
}
}
后序遍历二叉树
public static void PostOrder(TreeNode root){
//递归调用结束条件
if(root == null){
return;
}
//前序递归遍历root的左子树
PreOrder(root.left);
//前序递归遍历root的右子树
PreOrder(root.right);
//访问根节点数据域
System.out.println(root.val + " ");
}
非递归实现后序遍历二叉树
//方法一
public static void PostOrder(TreeNode root){
if(root == null){
return;
}
//定义两个栈
Stack<TreeNode> stackOne = new Stack<>();
Stack<TreeNode> stackTow = new Stack<>();
//将根节点放入栈一
stackOne.push(root);
while(stackOne != null){
//将根节点放入栈二
root = stackOne.pop();
stackTow.push(root);
//如果根节点的左节点非空,则入栈
if(root.left != null){
stackOne.push(root.left);
}
//若根节点的右节点非空,则入栈
if(root.right != null){
stackOne.push(root.right);
}
}
//用栈二输出树的值域
while(stackTow != null){
System.out.println(stackTow.pop().val + " ");
}
}
//方法二
public static void PostOrder(TreeNode root){
if(root == null){
return;
}
//定义栈
Stack<TreeNode> stacl = new Stack<>();
//将根节点入栈
stack.push(root);
//定义一个树节点
TreeNode node;
while(stack != null){
//将栈顶元素返回给结点node。但不删除栈顶元素
node = stack.peek();
//将树的左节点入栈,右节点入栈,输出值域
if(node.left != null && root != node.left && root != node.right){
stack.push(node.left);
}else if(node.right != null && root != node.right){
stack.push(node.right);
}else{
System.out.println(stack.pop().val + " ");
root = node;
}
}
}
//方法三
public static void PostOrder(){
TreeNode node = root;
element stack[100];
//栈初始化
int top = - 1;
while(node != null || top != - 1){
while(node != null){
//将node连同标志flag=1入栈
top++;
stack[top].ptr = node;
stack[top].flag = 1;
node = node.left;
}
while(top != null && stack[top].flag == 2){
//栈顶元素出栈并赋值给node
node = stack[top].ptr;
System.out.println(node.val);
}
if(top != - 1){
//栈顶元素标志改为2,遍历右子树
stack[top].flag = 2;
node = stack[top].ptr.right;
}
}
}
广度优先搜索(BFS)
public static void LevelOrder(TreeNode root){
if(root == null){
return;
}
//定义链表
ListedList<TreeNode> list = new ListedList<>();
//将根节点添加到链表中
list.add(root);
while(list != null){
//poll()方法相当于移除队头元素
TreeNode node = list.poll;
System.out.println(node.val);
if(node.left != null){
list.add(node.left);
}
if(node.right != null){
list.add(node.right);
}
}
}
广度优先搜索(BFS)—队列实现
public static void LevelOrder(TreeNode root){
if(root != null){
return;
}
TreeNode Queue[100], queue = null;
//队列初始化
int front = - 1, rear = - 1;
//根节点入队
Queue[++rear] = root;
while(front != rear){
//根节点出队并输出根节点值
queue = Queue[++front];
System.out.println(queue.data);
//若左节点非空,则入队
if(queue.left != null){
Queue[++rear] = queue.left;
}
//若右节点非空,则入队
if(queue.right != null){
Queue[++rear] = queue.right;
}
}
}
广度优先搜索(BFS)递归写法
public static void LevelOrder(TreeNode root){
int depth = depth(root);
for(int i = 0; i < depth; i++){
printLevel(root, i);
}
}
//计算树的层数
private static int depth(TreeNode root){
if(root == null){
return 0;
}
int leftDepth = depth(root.left);
int rightDepth = depth(root.right);
return Math.max(leftDepth, righDepth) + 1;
}
//输出结点对应的值
private static void printLevel(TreeNode root, int level){
if(root == null){
return 0;
}
if(level == 0){
System.out.println(" " + root.val);
}else{
printLevel(root.left, level - 1);
printLevel(root.right, level - 1);
}
}
深度优先搜索(DFS)
public static void DFStree(TreeNode root){
//定义栈
Stack<TreeNode> stack = new Stack<>();
//将根节点入栈
stack.add(root);
while(stack != null){
//将栈头元素出栈赋值给node
TreeNode node = stack.pop();
//输出node的值
System.out.println(node.val);
//若左节点非空,则入栈
if(node.left != null){
stac.push(node.left);
}
//若右节点非空,则入栈
if(node.right != null){
stack.push(node.right);
}
}
}
深度优先搜索递归写法
public static void DFStree(TreeNode root){
if(root == null){
return;
}
//输出根节点值
System.out.println(root.val);
//递归遍历左节点
DFStree(root.left);
//递归遍历右节点
DFStree(root.right);
}
构造函数—建立二叉树
import java.util.Scanner;
public static void Creat(){
TreeNode root;
//输入节点值,假设为字符
Scanner scan = new Scanner(System.in);
char ch = scan.nextChar();
//建立空树
if(ch == '#'){
root = null;
}else{
//将字符存入根节点的值域
root = new TreeNode;
root.data = ch;
//递归建立左子树
root.left = Creat();
//递归建立右子树
root.right = Creat();
}
return root;
}
析构函数—销毁二叉树
public static void Release(TreeNode root){
if(root == null){
return;
}
//释放左子树
Release(root.left);
//释放右子树
Release(root.right);
//释放根节点
delete root;
}