树和二叉树总结

一、定义

  1. 结点分类:树的结点包含一个数据元素和若干指向其子树的分支
  2. 度:结点拥有的子树数称为结点的度,度为0的结点称为叶子节点,树的结点时各结点度的最大值。
  3. 树的层数(深度):从根开始定义,根为第一层,树种的结点的最大层次称为树的深度或者高度。

二、树的存储结构

  1. 双亲表示法:在每个结点中,附设一个指示器指示双亲在数组中的位置
  2. 孩子表示法:在每个结点中,附设一个指示器指示孩子数和若干指示器指向孩子结点所在的位置
  3. 孩子兄弟表示法:data-firstchild-rightchild

三、二叉树的定义

  1. 满二叉树:在一棵二叉树中,所有分支结点都存在左子树和右子树,并且所有的叶子节点都在同一层上。
  2. 完全二叉树:完全二叉树是由满二叉树而引出来的,若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数(即1~h-1层为一个满二叉树),第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。

四、二叉树的性质:

  1. 在二叉树的第I层上至少有2^i-1个结点
  2. 深度为K的二叉树至多有2^k-1个结点
  3. 对任意二叉树T,如果其叶子节点数为n0,度为2的结点数为n2,则n0=n2+1。
  4. 具有N个结点的完全二叉树的深度为|log2N|(|x|表示不大于x的最大整数)+1。
  5. 如果对一颗有N个结点的完全二叉数的结点按层数编号,对任意结点I有:
    1. 如果I等于1,则结点无双亲,如果I大于1,则双亲为|I/2|
    2. 如果2*I>N,则结点I无左孩子,否则其左孩子是结点2I.
    3. 如果2*I+1>N,则结点I无右孩子,否则其右孩子是结点2I+1.

五、二叉树的遍历

二叉树的四种遍历方式

前序遍历
中序遍历
后序遍历
层次遍历

遍历之前先创建一个二叉树
首先声明结点类

public class TreeNode {
    public int data;
    public TreeNode leftChild;
    public TreeNode rightChild;

    public TreeNode(int data){
        this.data = data;
    }

}

然后创建一颗二叉树

/**
     * 构建二叉树
     * @param list   输入序列
     * @return
     */
    public static TreeNode createBinaryTree(LinkedList<Integer> list){
        TreeNode node = null;
        if(list == null || list.isEmpty()){
            return null;
        }
        Integer data = list.removeFirst();
        if(data!=null){
            node = new TreeNode(data);
            node.leftChild = createBinaryTree(list);
            node.rightChild = createBinaryTree(list);
        }
        return node;
    }

前序遍历

实现代码:

/**
     * 二叉树前序遍历   根-> 左-> 右
     * @param node    二叉树节点
     */
    public static void preOrderTraveral(TreeNode node){
        if(node == null){
            return;
        }
        System.out.print(node.data+" ");//根节点
        preOrderTraveral(node.leftChild);//左子树
        preOrderTraveral(node.rightChild);//右子树
    }

中序遍历

代码实现:

/**
     * 二叉树中序遍历   左-> 根-> 右
     * @param node   二叉树节点
     */
    public static void inOrderTraveral(TreeNode node){
        if(node == null){
            return;
        }
        inOrderTraveral(node.leftChild);
        System.out.print(node.data+" ");
        inOrderTraveral(node.rightChild);
    }

后序遍历

代码实现:

/**
     * 二叉树后序遍历   左-> 右-> 根
     * @param node    二叉树节点
     */
    public static void postOrderTraveral(TreeNode node){
        if(node == null){
            return;
        }
        postOrderTraveral(node.leftChild);
        postOrderTraveral(node.rightChild);
        System.out.print(node.data+" ");
    }

层序遍历

代码实现:

public static void levelOrder(TreeNode root){
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while(!queue.isEmpty()){
            root = queue.pop();
            System.out.print(root.data+" ");
            if(root.leftChild!=null) queue.add(root.leftChild);
            if(root.rightChild!=null) queue.add(root.rightChild);
        }
    }

非递归前序遍历

  1. 首先申请一个新的栈,记为stack;
  2. 声明一个结点treeNode,让其指向node结点;
  3. 如果treeNode的不为空,将treeNode的值打印,并将treeNode入栈,然后让treeNode指向treeNode的左结点,
  4. 重复步骤3,直到treenode为空;
  5. 然后出栈,让treeNode指向treeNode的右孩子
  6. 重复步骤3,直到stack为空.
    代码实现:
public static void preOrderTraveralWithStack(TreeNode node){
        Stack<TreeNode> stack = new Stack<TreeNode>();
        TreeNode treeNode = node;
        while(treeNode!=null || !stack.isEmpty()){
            //迭代访问节点的左孩子,并入栈
            while(treeNode != null){
                System.out.print(treeNode.data+" ");
                stack.push(treeNode);
                treeNode = treeNode.leftChild;
            }
            //如果节点没有左孩子,则弹出栈顶节点,访问节点右孩子
            if(!stack.isEmpty()){
                treeNode = stack.pop();
                treeNode = treeNode.rightChild;
            }
        }
    }
posted @ 2020-03-21 21:43  两小无猜  阅读(379)  评论(1编辑  收藏  举报