java 实现二叉树题目

原创 2017年09月11日 23:33:32

树是一种比较重要的数据结构,尤其是二叉树。二叉树是一种特殊的树,在二叉树中每个节点最多有两个子节点,

一般称为左子节点和右子节点(或左孩子和右孩子),并且二叉树的子树有左右之分,其次序不能任意颠倒。二叉树是递归定义的,

因此,与二叉树有关的题目基本都可以用递归思想解决,

本文包括:

  • 建树
  • 向树中插入一个节点
  • 依据树节点的值删除树中的一个节点
  • 先续遍历树中的所有节点
  • 中续遍历树中的所有节点
  • 后续遍历树中的所有节点
  • 得到二叉树的节点个数
  • 求二叉树的深度
  • 求二叉树第K层的节点个数
  • 求叶子节点个数

建树

public class LRTree {

    //节点对象
    class Node {
        public long value;

        public Node leftChild;

        public Node rightChild;

        public Node(long value) {
            this.value = value;
            leftChild = null;
            rightChild = null;
        }
    }

    public Node root;

    public Node getRoot() {
        return root;
    }

    public void setRoot(Node root) {
        this.root = root;
    }

    public LRTree() {
        root = null;
    }

    // 向树中插入一个节点
    public void insert(long value) {
        Node newNode = new Node(value);
        // 树是空的
        if (root == null)
            root = newNode;
        else {
            Node current = root;
            Node parentNode;
            while (true) {
                parentNode = current;
                if (value < current.value) {
                    current = current.leftChild;
                    // 要插入的节点为左孩子节点
                    if (current == null) {
                        parentNode.leftChild = newNode;
                        return;
                    }
                } else {
                    // 要插入的节点为右孩子节点
                    current = current.rightChild;
                    if (current == null) {
                        parentNode.rightChild = newNode;
                        return;
                    }
                }
            }
        }
    }


    /**
     * 依据树节点的值删除树中的一个节点
     */
    public boolean delete(int value) {
        // 遍历树过程中的当前节点
        Node current = root;
        // 要删除节点的父节点
        Node parent = root;
        // 记录树的节点为左孩子节点或右孩子节点
        boolean isLeftChild = true;
        while (current.value != value) {
            parent = current;
            // 要删除的节点在当前节点的左子树里
            if (value < current.value) {
                isLeftChild = true;
                current = current.leftChild;
            }
            // 要删除的节点在当前节点的右子树里
            else {
                isLeftChild = false;
                current = current.rightChild;
            }
            // 在树中没有找到要删除的节点
            if (current == null)
                return false;
        }
        // 要删除的节点为叶子节点
        if (current.leftChild == null && current.rightChild == null) {
            // 要删除的节点为根节点
            if (current == root)
                root = null;
                // 要删除的节点为左孩子节点
            else if (isLeftChild)
                parent.leftChild = null;
                // 要删除的节点为右孩子节点
            else
                parent.rightChild = null;
        }
        // 要删除的节点有左孩子节点,没有右孩子节点
        else if (current.rightChild == null) {
            // 要删除的节点为根节点
            if (current == null)
                root = current.leftChild;
                // 要删除的节点为左孩子节点
            else if (isLeftChild)
                parent.leftChild = current.leftChild;
                // 要删除的节点为右孩子节点
            else
                parent.rightChild = current.leftChild;
        }
        // 要删除的节点没有左孩子节点,有右孩子节点
        else if (current.leftChild == null) {
            // 要删除的节点为根节点
            if (current == root)
                root = root.rightChild;
                // 要删除的节点为左孩子节点
            else if (isLeftChild)
                parent.leftChild = current.rightChild;
                // 要删除的节点为右孩子节点
            else
                parent.rightChild = current.rightChild;
        }
        // 要删除的接节点既有左孩子节点又有右孩子节点
        else {
            Node successor = getSuccessor(current);
            // 要删除的节点为根节点
            if (current == root)
                root = successor;
                // 要删除的节点为左孩子节点
            else if (isLeftChild)
                parent.leftChild = successor;
                // 要删除的节点为右孩子节点
            else
                parent.rightChild = successor;
        }
        return true;
    }

    // 找到要删除节点的替补节点
    private Node getSuccessor(Node delNode) {
        // 替补节点的父节点
        Node successorParent = delNode;
        // 删除节点的替补节点
        Node successor = delNode;
        Node current = delNode.rightChild;
        while (current != null) {
            // successorParent指向当前节点的上一个节点
            successorParent = successor;
            // successor变为当前节点
            successor = current;
            current = current.leftChild;
        }
        // 替补节点的右孩子节点不为空
        if (successor != delNode.rightChild) {
            successorParent.leftChild = successor.rightChild;
            successor.rightChild = delNode.rightChild;
        }
        return successor;
    }


    /**
     * 调度方法
     * 测试用
     * @param traverseType
     */
    public void traverse(int traverseType) {
        switch (traverseType) {
            case 1:
                preOrder(root);
                break;
            case 2:
                inOrder(root);
                break;
            case 3:
                postOrder(root);
                break;
            default:
                break;
        }
    }

    /**
     * 先续遍历树中的所有节点
     * 做法:
     * 如果二叉树为空,空操作
     * 如果二叉树不为空,访问根节点,前序遍历左子树,前序遍历右子树
     */
    public void preOrder(Node currentRoot) {
        if (currentRoot != null) {
            //先输出当前节点
            System.out.print(currentRoot.value + " ");
            preOrder(currentRoot.leftChild);
            preOrder(currentRoot.rightChild);
        }
    }

    /**
     * 中续遍历树中的所有节点
     * 做法:
     * 如果二叉树为空,空操作。
     * 如果二叉树不为空,中序遍历左子树,访问根节点,中序遍历右子树
     * @param currentNode
     */
    public void inOrder(Node currentNode) {
        if (currentNode != null) {
            inOrder(currentNode.leftChild);
            //左节点输出完 输出当前节点
            System.out.print(currentNode.value + " ");
            inOrder(currentNode.rightChild);
        }
    }

    /**
     * 后续遍历树中的所有节点
     * 做法:
     * 如果二叉树为空,空操作
     * 如果二叉树不为空,后序遍历左子树,后序遍历右子树,访问根节点
     * @param currentNode
     */
    public void postOrder(Node currentNode) {
        if (currentNode != null) {
            postOrder(currentNode.leftChild);
            postOrder(currentNode.rightChild);
            //最后输出当前节点
            System.out.print(currentNode.value + " ");
        }
    }

    /**
     * 得到二叉树的节点个数
     * 做法:
     * 如果二叉树为空,节点个数为0
     * 如果二叉树不为空,二叉树节点个数 = 左子树节点个数 + 右子树节点个数 + 1
     * @param root
     * @return
     */
    public Integer GetNodeNum(Node root) {
        if (root == null) {
            //递归出口
            return 0;
        }
        return GetNodeNum(root.leftChild) + GetNodeNum(root.rightChild) + 1;
    }


    /**
     * 求二叉树的深度
     * 思考:如果二叉树为空,二叉树的深度为0
     * 如果二叉树不为空,二叉树的深度 = max(左子树深度, 右子树深度) + 1
     */
    public Integer GetDepth(Node root) {
        if (root == null) {
            return 0;
        }
        Integer depthLeft = GetDepth(root.leftChild);
        Integer depthRight = GetDepth(root.rightChild);
        return depthLeft > depthRight ? (depthLeft + 1) : (depthRight + 1);
    }

    /**
     * 求二叉树第K层的节点个数
     * 思考:如果二叉树为空或者k<1返回0
     * 如果二叉树不为空并且k==1,返回1
     * 如果二叉树不为空且k>1,返回左子树中k-1层的节点个数与右子树k-1层节点个数之和
     */
    public Integer GetNodeNumKthLevel(Node root, Integer k) {
        if (root == null || k < 1)
            return 0;
        if (k == 1)
            return 1;
        int numLeft = GetNodeNumKthLevel(root.leftChild, k - 1); // 左子树中k-1层的节点个数 递归左节点,k 为递归层数
        int numRight = GetNodeNumKthLevel(root.rightChild, k - 1); // 右子树中k-1层的节点个数 递归右节点,k 为递归层数
        return (numLeft + numRight);
    }

    /**
     * 求叶子节点个数
     * 思考:叶子节点,左右节点都是null,为叶子节点
     * 做法:
     * 如果二叉树为空,返回0
     * 如果二叉树不为空且左右子树为空,返回1
     * 如果二叉树不为空,且左右子树不同时为空,返回左子树中叶子节点个数加上右子树中叶子节点个数
     */
    public Integer GetLeafNodeNum(Node root) {
        if (root == null)
            return 0;
        if (root.leftChild == null && root.rightChild == null)
            return 1;
        int numLeft = GetLeafNodeNum(root.leftChild);
        int numRight = GetLeafNodeNum(root.rightChild);
        return (numLeft + numRight);
    }

}

测试调用类

public class LRTreeApp {
    public static void main(String[] args) {
        LRTree tree = init();
        System.out.println(tree.GetDepth(tree.getRoot()));
    }

    private static LRTree init() {
        LRTree tree = new LRTree();
        tree.insert(8);
        tree.insert(50);
        tree.insert(45);
        tree.insert(21);
        tree.insert(32);
        tree.insert(18);
        tree.insert(37);
        tree.insert(64);
        tree.insert(88);
        tree.insert(5);
        tree.insert(4);
        tree.insert(7);
        return tree;

    }

    private static void selectTree(LRTree tree) {
        System.out.print("--------先续遍历 --------");
        tree.traverse(1);
        System.out.println("");

        System.out.print("--------中续遍历 --------");
        tree.traverse(2);
        System.out.println();

        System.out.print("--------后续遍历-------- ");
        tree.traverse(3);
        System.out.println();

        System.out.print("--------二叉树的节点个数 --------");
        System.out.println(tree.GetNodeNum(tree.getRoot()));

        System.out.println("--------删除节点----------");
        System.out.println(tree.delete(7));

        System.out.print("--------先续遍历 -------- ");
        tree.traverse(1);
        System.out.println();

        System.out.print("--------中续遍历-------- ");
        tree.traverse(2);
        System.out.println();

        System.out.print("--------后续遍历 -------- ");
        tree.traverse(3);
        System.out.println();

        System.out.print("--------二叉树的节点个数-------- ");
        System.out.println(tree.GetNodeNum(tree.getRoot()));

        System.out.println("-------二叉树的深度---------");
        System.out.println(tree.GetDepth(tree.getRoot()));

        System.out.println("------二叉树第K层的节点个数--------");
        System.out.println(tree.GetNodeNumKthLevel(tree.getRoot(),5));

    }
}

未完待续

本文源码:https://github.com/527515025/JavaTest/tree/master/src/main/java/com/us/tree/LeftRightTree
参考:http://www.cnblogs.com/licheng/archive/2010/04/06/1705547.html
http://blog.csdn.net/luckyxiaoqiang/article/details/7518888

版权声明:本文为博主编写文章,未经博主允许转载,转载请注明出处。

面试中的二叉树题目,java描述

本文转载自http://blog.csdn.net/fightforyourdream/article/details/16843303**题目: 1. 前序、中序、后序遍历二叉树 2. 层序...
  • sinat_35209943
  • sinat_35209943
  • 2017年04月09日 17:57
  • 302

Java实现二叉树和常见的排序

前言这里总结对二叉树和排序做一下笔记,记不清的时候可以翻来看看。二叉树二叉树分为根节点,双亲节点,叶子节点,节点的度不能超多2,左孩子小于双亲节点,右孩子大于双亲节点。public class Tre...
  • qq_22271479
  • qq_22271479
  • 2017年07月06日 14:21
  • 590

【数据结构】之二叉树的java实现

二叉树的定义: 二叉树是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。...
  • wuwenxiang91322
  • wuwenxiang91322
  • 2013年10月02日 09:28
  • 80925

JAVA 数据结构-轻松搞定二叉树的面试题目

转载出处:http://blog.csdn.net/walkinginthewind/article/details/7518888 树是一种比较重要的数据结构,尤其是二叉树。二叉树是一种特殊的...
  • csdn_aiyang
  • csdn_aiyang
  • 2017年06月13日 15:57
  • 307

二叉树之Java实现二叉树基本操作

参考自《Java数据结构与算法》 定义一个节点类,使节点与二叉树操作分离 class Node { int value; Node leftChild; Node rightChild;...
  • fengrunche
  • fengrunche
  • 2016年08月25日 03:08
  • 6015

Java实现二叉树

二叉树:二叉树是一棵树,其中每个结点都不能有多余
  • u012736409
  • u012736409
  • 2014年08月05日 10:27
  • 3337

java实现二叉树的创建及5种遍历

用java实现的数组创建二叉树以及先序遍历,中序遍历,后序遍历三种遍历
  • ls5718
  • ls5718
  • 2016年04月23日 15:52
  • 2842

Java实现简单二叉树

B树       即二叉搜索树:       1.所有非叶子结点至多拥有两个儿子(Left和Right);       2.所有结点存储一个关键字;       3.非叶子结点的左指针指向小于其关键字...
  • liaodehong
  • liaodehong
  • 2016年10月09日 18:23
  • 1796

java代码实现排序二叉树

创建排序二叉树的步骤:          1、以根节点为当前节点开始搜索          2、拿新节点的值和当前节点的值比较          3、如果新节点的值更大,则以当前结点的右子节点作为新的...
  • yanglun1
  • yanglun1
  • 2015年04月29日 17:01
  • 937

二叉树的顺序存储及其Java实现

顺序存储充分利用满二叉树的特性,即每层的节点数分别为1、2、4、8。。。2i+1,一个深度为i的二叉树最多只能包含2i-1个节点,因此只要定义一个长度为2i-1的数组即可存储这颗二叉树。   对于...
  • bruce_6
  • bruce_6
  • 2014年07月28日 09:30
  • 2117
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java 实现二叉树题目
举报原因:
原因补充:

(最多只允许输入30个字)