首页 > 代码库 > 11求二叉树中节点的最大距离

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 =http://www.mamicode.com/ 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 _10MaxDistance { 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 =http://www.mamicode.com/ data;103             this.left = left;104             this.right = right;105             this.leftDepth = leftDepth;106             this.rightDepth = rightDepth;107         }108     }109     110 }
View Code

运行结果:

建树过程(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 =http://www.mamicode.com/ 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             //当前节点的最大为左右子树最大深度+111         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 _10_1MaxDistance { 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 =http://www.mamicode.com/ 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

11求二叉树中节点的最大距离