树和二叉树基本概念及常用操作Java实现

树的基本概念

  1. 结点的度:一个结点含有的子结点的个数称为该结点的度;
  2. 叶结点或终端结点:度为0的结点称为叶结点;
  3. 非终端结点或分支结点:度不为0的结点;
  4. 双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点;
  5. 孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点;
  6. 兄弟结点:具有相同父结点的结点互称为兄弟结点;
  7. 树的度:一棵树中,最大的结点的度称为树的度;
  8. 结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推;
  9. 树的高度或深度:树中结点的最大层次;
  10. 堂兄弟结点:双亲在同一层的结点互为堂兄弟;
  11. 结点的祖先:从根到该结点所经分支上的所有结点;
  12. 子孙:以某结点为根的子树中任一结点都称为该结点的子孙。
  13. 森林:由m(m>=0)棵互不相交的树的集合称为森林;
  14. 无序树:树中任意节点的子结点之间没有顺序关系,这种树称为无序树,也称为自由树;
  15. 有序树:树中任意节点的子结点之间有顺序关系,这种树称为有序树;
  16. 二叉树:每个节点最多含有两个子树的树称为二叉树;
  17. 完全二叉树:若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树
  18. 满二叉树:除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树。
  19. 哈夫曼树:带权路径最短的二叉树称为哈夫曼树或最优二叉树;

树的节点类的定义

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;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值