美文网首页程序员
数据结构之二叉树

数据结构之二叉树

作者: 王小冬 | 来源:发表于2018-05-25 21:20 被阅读18次

    数据结构之二叉树

    本文讲解二叉树的基本操作:

    • 查找节点
    • 计算树的高度
    • 清空树
    • 递归遍历:先序遍历、中序遍历、后序遍历
    • 按层遍历
    • 前序、中序的非递归遍历
    • 树的左旋和右旋

    来看一下树的结构:

    class TreeNode {
        String value;
        TreeNode left;
        TreeNode right;
        public TreeNode() {
            
        }
        public TreeNode(String value) {
            this.value = value;
        }
    }
    

    首先,为了方便后面看到效果,先手动初始化一个有4个节点的二叉树:

    Tree tree = new Tree();
    TreeNode root = new TreeNode("root");
    TreeNode node1 = new TreeNode("ndoe1");
    TreeNode node2 = new TreeNode("ndoe2");
    TreeNode node3 = new TreeNode("ndoe3");
    root.left = node1;
    root.right = node2;
    node1.left = node3;
    

    1. 查找节点

    //查找节点
    public TreeNode findNode(TreeNode treeNode, String value) {
      if(null == treeNode)
        return null;
    
      if(treeNode.value.equals(value))
        return treeNode;
    
      TreeNode leftNode = findNode(treeNode.left, value);//递归左子树
      TreeNode rightNode = findNode(treeNode.right, value);//递归右子树
      if(leftNode.value.equals(value))
        return leftNode;
      if(rightNode.value.equals(value))
        return rightNode;
    
      return null;
    }
    

    2. 计算树的深度

    //计算树的深度
    //递归方法
    public int deepth(TreeNode treeNode) {
      if(treeNode == null)
        return 0;
      int left = deepth(treeNode.left);
      int right = deepth(treeNode.right);
      return left > right? left + 1: right + 1;
    }
    

    3. 清空树

    //清空二叉树
    public void clearTreeNode(TreeNode treeNode) {
      if(null != treeNode) {
        clearTreeNode(treeNode.left);
        clearTreeNode(treeNode.right);
        treeNode = null;
      }
    }
    

    4. 递归遍历

    //遍历1 先序遍历
    public void showDLR(TreeNode treeNode) {
      if(null != treeNode) {
        showData(treeNode);
        showDLR(treeNode.left);
        showDLR(treeNode.right);
      }
    }
    //遍历2 中序遍历
    public void showLDR(TreeNode treeNode) {
      if(null != treeNode) {
        showLDR(treeNode.left);
        showData(treeNode);
        showLDR(treeNode.right);
      }
    }
    //遍历3 后序遍历
    public void showLRD(TreeNode treeNode) {
      if(null != treeNode) {
        showLRD(treeNode.left);
        showLRD(treeNode.right);
        showData(treeNode);
      }
    }
    

    5. 按层遍历

    //遍历4 按层遍历 借助队列 先进先出
    public void showByLevel(TreeNode treeNode) {
      if(null == treeNode)
        return;
    
      LinkedList<TreeNode> list = new LinkedList<>();
      TreeNode current;
      list.offer(treeNode);//将根节点入队
    
      while(!list.isEmpty()) {
        current = list.poll();//队首出队
        showData(current);//打印节点
        if(null != current.left) {
          list.offer(current.left);
        }
        if(null != current.right) {
          list.offer(current.right);
        }
      }
    }
    

    运行结果:

    树的深度是:3
    先序遍历:
    root-->ndoe1-->ndoe3-->ndoe2-->
    中序遍历:
    ndoe3-->ndoe1-->root-->ndoe2-->
    后序遍历:
    ndoe3-->ndoe1-->ndoe2-->root-->
    按层遍历
    root-->ndoe1-->ndoe2-->ndoe3-->
    

    6. 先序,中序遍历的非递归实现

    //遍历5 前序遍历的非递归实现
    public void showDLRNotRecursion(TreeNode treeNode) {
      Stack<TreeNode> stack = new Stack<>();
      TreeNode node = treeNode;
      while(null != node || stack.size() >0) {
        while(null != node) {
          showData(node);
          stack.push(node);
          node = node.left;
        }
        if(stack.size() > 0) {
          node = stack.pop();
          node = node.right;
        }
      }
    }
    //遍历6  中序遍历的非递归实现
    public void showLDRNotRecursion(TreeNode treeNode) {
      Stack<TreeNode> stack = new Stack<>();
      TreeNode node = treeNode;
      while(null != node || stack.size() > 0) {
        while(null != node) {
          stack.push(node);
          node = node.left;
        }
        if(stack.size() > 0) {
          node = stack.pop();
          showData(node);
          node = node.right;
        }
      }
    }
    

    7. 二叉树的左旋和右旋

    • 左旋:节点右儿子的左儿子(若存在)变为节点的右儿子,节点变为右儿子的左儿子;
    • 右旋:节点左二子的右儿子(若存在)变为节点的左二子,节点变为左二子的右儿子。

    举个例子:

    二叉树的左旋右旋.png

    可以看到,如果旋转前是一个二叉排序树,那么旋转后仍然是一个二叉排序树。

    相关文章

      网友评论

        本文标题:数据结构之二叉树

        本文链接:https://www.haomeiwen.com/subject/uctpjftx.html