树直径、二叉树直径 Tree diameter (Longest path in an undirected tree)

树直径问题其实就好像在一个无向无环图中找一条最长的路径,核心思想其实也很简单:

首先从任意一个节点开始BFS找距离最远能到达的点(以该点作为根节点树的最深层),假设到达点为V,再以V为根节点找最远能到达的点(即以V为根节点树的最深层),两次BFS即可解决。

按照上述方法,其实最开始任意选的那个点就是最长路径中的一个节点而已,这个节点可能是最长路径的端点也有可能是路径中的一点。


代码:

diametern2

#include <bits/stdc++.h>
 
using namespace std;

class Graph {
 	int V;
 	list<int> *adj;
public:
	Graph(int v) : V(v){adj = new list<int>[V];}
	void addEdge(int u, int v);
	void longestPathLength();
	pair<int, int >BFS(int u);

}; 

void Graph::addEdge(int u, int v) {
  adj[u].push_back(v);
  adj[v].push_back(u); 	
}

pair<int, int> Graph::BFS(int u) {
	int dis[V];
	fill(dis, dis + V, -1);

	queue<int> q;
	q.push(u);
	dis[u] = 0;
	while(!q.empty()) { 
		int t = q.front();
		q.pop();
		for(auto it = adj[t].begin(); it != adj[t].end(); ++it) {
		 	if(dis[*it] == -1) {
		 	 	q.push(*it);
		 	 	dis[*it] = dis[t] + 1;
		 	}
		}
 	}
 	int maxDis = 0;
 	int idx = -1;
 	for(int i = 0; i < V; ++i) {
 	 	if(dis[i] > maxDis) {
 	 	 	idx = i;
 	 	 	maxDis = dis[i];
 	 	}
 	}
 	return make_pair(idx, maxDis);
}

void Graph::longestPathLength() {
   pair<int, int> t1, t2;
   t1 = BFS(0);
   t2 = BFS(t1.first);
   cout << 	"Longest path is from " << t1.first << " to " << t2.first << " of length " << t2.second << endl;
}

int main(){
    ios::sync_with_stdio(false);
    Graph g(10);
    g.addEdge(0, 1);
    g.addEdge(1, 2);
    g.addEdge(2, 3);
    g.addEdge(2, 9);
    g.addEdge(2, 4);
    g.addEdge(4, 5);
    g.addEdge(1, 6);
    g.addEdge(6, 7);
    g.addEdge(6, 8);

    g.longestPathLength();

    return 0;   
}

对于求二叉树的直径其实更简单,取根节点的左右孩子树高之和加一和左右孩子中的直径三者中的最大值(直径可能不包含根节点),同理孩子节点递归向下求,核心代码:


 int Diameter(Node *root, int *hegiht) {
     if(root == NULL) {
         *hegiht = 0;
         return 0;
     }
     int lh = 0, rh = 0;
     int ldiameter = 0, rdiameter = 0;
     ldiameter = Diameter(root->left, &lh);
     rdiameter = Diameter(root->right, &rh);
     *height = max(lh, rh) + 1; // recording height of tree
     return max(lh + rh + 1, max(ldiameter, rdiameter));
 }



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值