求樹的“直徑”以及所想到的

算法導論22.2-7題:樹T=(V,E)的直徑(diameter)定義爲max(u,v),亦即,樹的直徑是樹中所有最短路徑長度中的最大值。試寫出計算樹的直徑的有效算法,並分析算法的運行時間。

如果這裏的樹T是簡單的二叉樹或者多叉樹,我們可以用遞歸來解決(Diameter(tree T)表示T的直徑);

1. 求出T左子樹的最深節點的深度Dleft,求出T右子樹最深節點的深度Dright。

2. 則T的直徑爲:max(Dleft + Dright + 1, Diameter(T->left), Diameter(T->right))

這裏使用遞歸是因爲有可能直徑不經過根節點。時間複雜度爲O(n^2).

下面還有個優化方法,可以使得時間複雜度爲O(n).

Optimized implementation: The above implementation can be optimized by calculating the height in the same recursion rather than calling a height() separately. Thanks to Amar for suggesting this optimized version. This optimization reduces time complexity to O(n).

/*The second parameter is to store the height of tree.
   Initially, we need to pass a pointer to a location with value
   as 0. So, function should be used as follows:
 
   int height = 0;
   struct node *root = SomeFunctionToMakeTree();
   int diameter = diameterOpt(root, &height); */
int diameterOpt(struct node *root, int* height)
{
  /* lh --> Height of left subtree
      rh --> Height of right subtree */
  int lh = 0, rh = 0;
  
  /* ldiameter  --> diameter of left subtree
      rdiameter  --> Diameter of right subtree */
  int ldiameter = 0, rdiameter = 0;
  
  if(root == NULL)
  {
    *height = 0;
     return 0; /* diameter is also 0 */
  }
  
  /* Get the heights of left and right subtrees in lh and rh
    And store the returned values in ldiameter and ldiameter */
  ldiameter = diameterOpt(root->left, &lh);
  rdiameter = diameterOpt(root->right, &rh);
  
  /* Height of current node is max of heights of left and
     right subtrees plus 1*/
  *height = max(lh, rh) + 1;
  
  return max(lh + rh + 1, max(ldiameter, rdiameter));
}



如果這裏的樹進化爲了圖,該如何求出它的直徑呢?

1. 從任意一個節點u開始做第一遍BFS,得到距離u最遠的那個節點v

2. 從節點v開始做第二遍BFS,得到距離v最遠的節點 e, 那 v 到 e 就是直徑

證明:

1. 如果 u 在直徑路徑上:反證法, 如果v不在直徑上,那根據直徑的定義,必然存在一點v2在直徑上,使得dist(u->v2) 大於 dist(u->v), 而這和BFS算法 v是從u 出發到達的所有節點中離u最遠相矛盾。

2. 如果 u 不在直徑路經上, 反證法,看圖:

u ----- w ------- v

             /

x ----------y ----------z

上圖中,u-->v 是第一遍BFS算出來的路徑,x-->z 是直徑路徑,反證法假設v 不在直徑路徑上,如圖所示。根據樹和聯通圖的定義,u->v中必然存在一點w, 和x->z中的某點y 相連通,或者說必然存在一個路徑 w--y ,鏈接uv和xz。

代碼就不寫了,不是很複雜。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章