zoukankan      html  css  js  c++  java
  • 11求二叉树中节点的最大距离

    转载请注明出处:http://www.cnblogs.com/wuzetiandaren/p/4253605.html

    声明:现大部分文章为寻找问题时在网上相互转载,此博是为自己做个记录记录,方便自己也方便有类似问题的朋友,本文的思想也许有所借鉴,但源码均为本人实现,如有侵权,请发邮件表明文章和原出处地址,我一定在文章中注明。谢谢。

    题目:如果我们把二叉树看成一个图,一棵树显示是一颗有向无环图,定义"距离"为两节点之间边的个数(不考虑方向)。写一个程序,求一棵二叉树中相距最远的两个节点之间的距离。

    题目分析:《编程之美》一书上提供了这样一种思路:计算一个二叉树的最大距离有两个情况:

    • 情况A: 路径经过左子树的最深节点,通过根节点,再到右子树的最深节点。
    • 情况B: 路径不穿过根节点,而是左子树或右子树的最大距离路径,取其大者。

      只需要计算这两个情况的路径距离,并取其大者,就是该二叉树的最大距离。

    注:求得的距离大小是唯一的,但是路径却不一定唯一。

        

    算法设计:

      定义节点的数据结构,有数据,左孩子,有孩子,左边最大深度,右边最大深度。

        //节点的数据结构
        private static class Node {
            public int data;
            public Node left;   //指向左子树
            public Node right;  //指向右子树
            public int leftDepth; //左边的最大长度
            public int rightDepth; //右边的最大长度
            public Node() {
                super();
                // TODO Auto-generated constructor stub
            }
            
            public Node(int data, Node left, Node right, int leftDepth,
                    int rightDepth) {
                super();
                this.data = data;
                this.left = left;
                this.right = right;
                this.leftDepth = leftDepth;
                this.rightDepth = rightDepth;
            }
        }
    节点数据结构

      构造二叉树,传入根节点。

      1.如果节点为空则结束。
      2.若左(右)孩子为空,则让该节点的左(右)最大深度为0。
      3.如果左子树不为空,递归求左子的树节点之间的最大距离。
      4.如果右子树不为空,递归求右子的树节点之间的最大距离。
      5.如果左子树不为空,则root的左边深度+1。
      6.如果右子树不为空,则root的右边深度+1。
      7.更新最长距离。

    java实现源码:

      1 package com.interview;
      2 
      3 
      4 /**
      5  * 题目:求二叉树中节点的最大距离...
      6  * @author wjh
      7  *
      8  */
      9 public class _11_1MaxDistance {
     10 
     11     /**
     12      * @param args
     13      */
     14     public static int maxdistance=0;
     15     public static void main(String[] args) {
     16         int[] a = {20,5,4,3,2,7,13,11};//{20,5,22,4,7,25,13,36,42,11,24};
     17         Node root = null;
     18         root = createTree( root, a);   //1)建树
     19         maxDistance(root);    //2)求该树的节点间的最大距离
     20         System.out.println("该二叉树的节点的最大距离为:"+maxdistance);
     21     }
     22 
     23     
     24     //求树的节点之间的最大距离
     25     private static void maxDistance(Node root){
     26         if(root==null){   //如果节点为空则结束
     27             return;
     28         }           
     29         //点的左右最大深度已经初始化为0
     30         if(root.left!=null){ //1)如果左子树不为空,递归求左子树节点之间的最大距离
     31             maxDistance(root.left);
     32         }
     33         if(root.right!=null){ //2)如果右子树不为空,递归求右子树节点之间的最大距离
     34             maxDistance(root.right);
     35         }
     36         if(root.left!=null){ //3)如果左子树不为空,则root的左边深度+1
     37             int tempDistance = max(root.left.leftDepth,root.left.rightDepth);
     38             root.leftDepth = tempDistance+1;
     39         }
     40         if(root.right!=null){ //4)如果右子树不为空,则root的右边深度+1
     41             int tempDistance = max(root.right.leftDepth,root.right.rightDepth);
     42             root.rightDepth = tempDistance+1;
     43         }
     44         int distance = root.leftDepth+root.rightDepth;
     45         if(distance>maxdistance){   //5)更新最长距离
     46             maxdistance = distance;
     47         }
     48     }
     49     
     50     
     51     //创建二叉排序树
     52     public static Node  createTree(Node root, int[] r){
     53         int n = r.length;
     54         System.out.println("建树过程(a<--b表示在a左边插入b;a-->b表示在a右边插入b):");
     55         for(int i=0;i<n;i++){
     56             Node child = new Node(r[i],null,null,0,0);//点的左右最大深度已经初始化为0
     57             root = insert(root, child);
     58         } 
     59         return root;
     60     }
     61         
     62     //二叉排序树的插入算法
     63     public static Node insert(Node root, Node child){
     64         //寻找插入位置
     65         if(root==null){
     66             root = child;
     67             System.out.println(root.data);
     68         }
     69         else 
     70             if(root.data>child.data){
     71                 System.out.print(root.data+"<--");//在root左边插入
     72                 root.left = insert(root.left, child);
     73             }
     74             else{
     75                 System.out.print(root.data+"-->"); //在root右边插入
     76                 root.right = insert(root.right,child);
     77             }    
     78         return root;
     79     }    
     80     
     81     
     82     //求两个数中的较大的
     83     private static int max(int a, int b){
     84         return (a>=b?a:b);
     85     }
     86     
     87     //节点的数据结构
     88     private static class Node {
     89         public int data;
     90         public Node left;   //指向左子树
     91         public Node right;  //指向右子树
     92         public int leftDepth; //左边的最大长度
     93         public int rightDepth; //右边的最大长度
     94         public Node() {
     95             super();
     96             // TODO Auto-generated constructor stub
     97         }
     98         
     99         public Node(int data, Node left, Node right, int leftDepth,
    100                 int rightDepth) {
    101             super();
    102             this.data = data;
    103             this.left = left;
    104             this.right = right;
    105             this.leftDepth = leftDepth;
    106             this.rightDepth = rightDepth;
    107         }
    108     }
    109     
    110 }
    完整源码

    运行结果:

    建树过程(a<--b表示在a左边插入b;a-->b表示在a右边插入b):
    20
    20<--5
    20<--5<--4
    20<--5<--4<--3
    20<--5<--4<--3<--2
    20<--5-->7
    20<--5-->7-->13
    20<--5-->7-->13<--11
    该二叉树的节点的最大距离为:6

    拓展:

    博客园另一位博友(http://www.cnblogs.com/miloyip/archive/2010/02/25/1673114.html)的提供了这样一种思路:

      情况A 及 B 需要不同的信息: A 需要子树的最大深度,B 需要子树的最大距离。只要函数能在一个节点同时计算及传回这两个信息,代码就可以很简单:

    节点的数据结构:

        //节点的数据结构
        private static class Node {
            public int data;
            public Node left;   //指向左子树
            public Node right;  //指向右子树
            public Node() {
                super();
                // TODO Auto-generated constructor stub
            }    
            public Node(int data, Node left, Node right) {
                super();
                this.data = data;
                this.left = left;
                this.right = right;
            }
        }
    节点数据结构

    结果数据结构:

        //结果的数据结构
        private static class Result{
            public int maxDistance;
            public int maxDepth;
            public Result() {
                super();
                // TODO Auto-generated constructor stub
            }
            public Result(int maxDistance, int maxDepth) {
                super();
                this.maxDistance = maxDistance;
                this.maxDepth = maxDepth;
            }
        }
    结果的数据结构

    求节点距离的算法设计及算法实现:

      1.如果root 为空,则返回{0,-1}
      2. 递归求左右子树的result.
      3.当前节点的最大距离为  [左右子树的最大距离]   与  [ 左右子树最大深度之和+2]   的最大值;当前节点的最大为左右子树最大深度+1.

     1     //求节点最大距离
     2     private static Result maxDistance(Node root){
     3         if(root==null){  //1)如果root 为空,则返回empty
     4             Result empty = new Result(0,-1);
     5             return empty;
     6         }
     7         Result left = maxDistance(root.left);//2) 递归求左右子树的result
     8         Result right = maxDistance(root.right);
     9         //3)当前节点的最大距离为左右子树的最大距离与左右子树最大深度+2 的最大值;
    10             //当前节点的最大为左右子树最大深度+1
    11         int thisDistance = max(max(left.maxDistance,right.maxDistance),
    12                 left.maxDepth+right.maxDepth+2);
    13         int thisDepth = max(left.maxDepth,right.maxDepth)+1;
    14         Result empty = new Result(thisDistance,thisDepth);
    15         return empty;
    16     }
    算法代码

      可以看到在进入节点时,如果节点为 NULL,会传回一个 empty 变量。比较奇怪的是 empty.maxDepth = -1,目的是让叶子节点的左右子树都为空,当叶子节点调用函数将maxDepth  +1 后,把叶子节点的最大深度置为 0。

    完整的java实现源码:

      1 package com.interview;
      2 
      3 
      4 /**
      5  * 题目:求二叉树中节点的最大距离...
      6  * @author wjh
      7  *
      8  */
      9 public class _11_2MaxDistance {
     10 
     11     /**
     12      * @param args
     13      */
     14     public static void main(String[] args) {
     15         int[] a = {20,5,4,3,2,7,13,11};//{20,5,22,4,7,25,13,36,42,11,24};
     16         Node root = null;
     17         root = createTree( root, a);   //1)建树
     18         Result result = maxDistance(root);    //2)求该树的节点间的最大距离
     19         System.out.println("该二叉树的节点的最大距离为:"+result.maxDistance);
     20 
     21     }
     22     
     23     //求节点最大距离
     24     private static Result maxDistance(Node root){
     25         if(root==null){  //1)如果root 为空,则返回empty
     26             Result empty = new Result(0,-1);
     27             return empty;
     28         }
     29         Result left = maxDistance(root.left);//2) 递归求左右子树的result
     30         Result right = maxDistance(root.right);
     31         //3)当前节点的最大距离为左右子树的最大距离与左右子树最大深度+2 的最大值;
     32             //当前节点的最大为左右子树最大深度+1
     33         int thisDistance = max(max(left.maxDistance,right.maxDistance),
     34                 left.maxDepth+right.maxDepth+2);
     35         int thisDepth = max(left.maxDepth,right.maxDepth)+1;
     36         Result empty = new Result(thisDistance,thisDepth);
     37         return empty;
     38     }
     39     
     40     //创建二叉排序树
     41     public static Node  createTree(Node root, int[] r){
     42         int n = r.length;
     43         System.out.println("建树过程(a<--b表示在a左边插入b;a-->b表示在a右边插入b):");
     44         for(int i=0;i<n;i++){
     45             Node child = new Node(r[i],null,null);//点的左右最大深度已经初始化为0
     46             root = insert(root, child);
     47         } 
     48         return root;
     49     }
     50         
     51     //二叉排序树的插入算法
     52     public static Node insert(Node root, Node child){
     53         //寻找插入位置
     54         if(root==null){
     55             root = child;
     56             System.out.println(root.data);
     57         }
     58         else 
     59             if(root.data>child.data){
     60                 System.out.print(root.data+"<--");//在root左边插入
     61                 root.left = insert(root.left, child);
     62             }
     63             else{
     64                 System.out.print(root.data+"-->"); //在root右边插入
     65                 root.right = insert(root.right,child);
     66             }    
     67         return root;
     68     }    
     69     
     70     
     71     //求两个数中的较大的
     72     private static int max(int a, int b){
     73         return (a>=b?a:b);
     74     }
     75     
     76     //节点的数据结构
     77     private static class Node {
     78         public int data;
     79         public Node left;   //指向左子树
     80         public Node right;  //指向右子树
     81         public Node() {
     82             super();
     83             // TODO Auto-generated constructor stub
     84         }    
     85         public Node(int data, Node left, Node right) {
     86             super();
     87             this.data = data;
     88             this.left = left;
     89             this.right = right;
     90         }
     91     }
     92     //结果的数据结构
     93     private static class Result{
     94         public int maxDistance;
     95         public int maxDepth;
     96         public Result() {
     97             super();
     98             // TODO Auto-generated constructor stub
     99         }
    100         public Result(int maxDistance, int maxDepth) {
    101             super();
    102             this.maxDistance = maxDistance;
    103             this.maxDepth = maxDepth;
    104         }
    105     }
    106 }
    完整源码

    运行结果:

    建树过程(a<--b表示在a左边插入b;a-->b表示在a右边插入b):
    20
    20<--5
    20<--5<--4
    20<--5<--4<--3
    20<--5<--4<--3<--2
    20<--5-->7
    20<--5-->7-->13
    20<--5-->7-->13<--11
    该二叉树的节点的最大距离为:6

  • 相关阅读:
    mac pro发热发热发热
    从零开始搭建Vue组件库
    Charles模拟弱网测试
    webpack
    异步加载脚本
    Angular
    JavaScript模板语言
    Node.js
    gulp
    jsonp原理
  • 原文地址:https://www.cnblogs.com/wuzetiandaren/p/4253605.html
Copyright © 2011-2022 走看看