树Tree

383 阅读3分钟

树结构

一、树结构中常见术语

(1)结点的度(Degree):结点的子树个数。

(2)树的度:树的所有结点中最大的度数。

(3)叶结点(Leaf):度为0的结点。

(4)父结点(Parent):有子树的结点是其子树的根结点的父结点。

(5)子节点(Child):若A结点是B结点的父结点,则称B结点是A结点的子结点。

(6)兄弟结点(Sibling):具有同一父结点的各结点彼此是兄弟结点。

(7)路径和路径长度:从结点n1到nk的路径为一个结点序列。路径所包含的边的个数为路径的长度。

(8)祖先结点(Ancestor):沿树根到某一结点路径上的所有结点都是这个结点的祖先结点。

(9)子孙结点(Descendant):某一结点的子树中所有结点是这个结点的子孙。

(10)结点的层次(Level):规定根结点在1层,其他任一结点的层数是其父节点的层数加1。

(11)树的深度(Depth):树中所有结点中的最大层次是这棵树的深度。

二、认识常见的树结构

满二叉树

定义:指的是树的每一层从左到右依次遍满的。

image.png

它的节点个数为:2^n-1 (n代表层数)

完全二叉树

定义:树的叶子节点在最后一层,或者是倒数第二层,所有的叶子节点都向左边聚拢,如果跳过左边的那么就不是一颗完全二叉树了。

image.png

平衡二叉树

定义:假如不是空树,任何一个结点的左子树与右子树都是平衡二叉树,并且高度之差的绝对值不超过1。

image.png

二叉排序树

定义:一颗空树,或者满足以下条件的树,每一个节点的左孩子小于当前节点的值,每一个节点的右孩子大于当前节点的值。

image.png

三、树结构中的相关性质

  • 性质1:一颗深度为n二叉树上节点最多为2^n -1 个 (n代表树的层数)

  • 性质2:一颗二叉树第n层的节点最多右 2^(n-1) 个

  • 性质3:n个节点的二叉树,他的高度最少为log2为底(n+1) 层

四、树的遍历方式

  • 树的遍历方式无非就是三种 前序遍历、中序遍历、后序遍历
//以这个作为树的节点类,接下来的操作都是针对这个节点来操作的
public static class TreeNode{
    Integer val;
    TreeNode left;
    TreeNode right;
    public TreeNode(Integer val) {
        this.val = val;
    }
}

前序遍历

递归方式

遍历方式首先打印头节点、然后打印左节点、然后打印右节点

  • coding
public static void preOrder(TreeNode node){
    if (node == null){
        return;
    }
    System.out.print(node.val + " ");
    if (node.left!=null){
        preOrder(node.left);
    }
    if (node.right!=null){
        preOrder(node.right);
    }
}

使用栈进行遍历

  • 思路:
  1. 1、首先申请一个栈 记作stack , 首先将头节点放进去
  2. 2、从栈中弹出刚才的节点 , 记作cur,然后打印cur的值
  3. 3、如果cur.right 不为空,则压入
  4. 4、如果cur.left 不为空,则压入 , 一定是先压入右节点,然后在压入左节点
public static void proOrderStack(TreeNode head){
    if (head == null){
        return;
    }
    Stack<TreeNode> stack = new Stack<>();
    stack.push(head);
    while(!stack.isEmpty()){
        TreeNode cur = stack.pop();
        System.out.print(cur.val + " ");
        if (cur.right!=null){
            stack.push(cur.right);
        }
        if (cur.left!=null){
            stack.push(cur.left);
        }
    }
}

中序遍历

递归方式

遍历方式首先打印左节点、然后打印头节点、然后打印右节点

  • coding
public static void inOrder(TreeNode node){
    if (node == null){
        return;
    }
    if (node.left!=null){
        inOrder(node.left);
    }
    System.out.print(node.val + " ");
    if (node.right!=null){
        inOrder(node.right);
    }
}

使用栈进行遍历

  • 实现思路:
  1. 申请一个栈 stack,使用cur 保存以下头节点
  2. 首先将cur压入栈对于cur节点为头节点的整颗子树来说,依次把左侧边界节点入栈,不停的cur = cur.left
  3. 发现cur为空的时候,从栈中弹出来一个元素并打印,并记录,并且让cur = node.right
  4. 只有当stack为空或者cur == null 的时候结束
public static void inOrderStack(TreeNode head){
    if (head == null){
        return;
    }
    Stack<TreeNode> stack = new Stack<>();
    TreeNode cur = head;
    while(!stack.isEmpty() || cur!=null){
        if (cur!=null){
            stack.push(cur);
            cur = cur.left;
        }else{
            cur = stack.pop();
            System.out.print(cur.val + " ");
            cur = cur.right;
        }
    }
}

后序遍历的方式

递归方式

遍历方式先打印左节点、然后打印右节点、然后打印根节点

  • coding
public static void postOrder(TreeNode node){
    if (node == null){
        return;
    }
    if (node.left!=null){
        postOrder(node.left);
    }
    if (node.right!=null){
        postOrder(node.right);
    }
    System.out.print(node.val + " ");
}

使用栈进行遍历

  • 思路
  1. 申请两个栈 分别为 stack1、stack2
  2. 首先是将头节点压入到stack1中,然后弹出stack1,放入到stack2里,记作cur,如果cur的左节点不为空,压入左节点,其次是右节点不为空压入右节点。然后依次重复
  3. 然后stack2不为空,则弹出打印,一直到stack2为空为止。
public static void postOrderStack(TreeNode head){
    if (head == null) return;
    Stack<TreeNode> stack1 = new Stack<>();
    Stack<TreeNode> stack2 = new Stack<>();
    stack1.push(head);
    while(!stack1.isEmpty()){
        TreeNode cur = stack1.pop();
        stack2.push(cur);
        if (cur.left!=null){
            stack1.push(cur.left);
        }
        if (cur.right!=null){
            stack1.push(cur.right);
        }
    }
    while(!stack2.isEmpty()){
        System.out.print(stack2.pop().val + " ");
    }
}

二叉树按照层次遍历

遍历思路:使用队列

1、首先创建一个队列Queue,并将头节点放进来

2、当队列不为空的情况下,从队列中取出来一个元素,并且判断这个元素是否存在左节点和右节点,如果说存在先将左节点加入到队列,然后将右节点加入到队列中去。 一次循环,一直到这个队列为空 停。

    public static void level(TreeNode head){
        if (head == null){
            return;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(head);
        while(!queue.isEmpty()){
            TreeNode cur = queue.poll();
            System.out.print(cur.val + " ");
            if (cur.left!=null){
                queue.add(cur.left);
            }
            if (cur.right!=null){
                queue.add(cur.right);
            }
        }
    }
------》》》将会持续更新