算法导论-22.2-7-树的直径

来源:互联网 发布:linux 开启端口号 编辑:程序博客网 时间:2024/06/05 02:27

一、题目

树T=(V,E)的直径(diameter)定义为max(u,v),亦即,树的直径是树中所有最短路径长度中的最大值。试写出计算树的直径的有效算法,并分析算法的运行时间。


二、思考

step1:以树中任意一个结点为源点,进行一次广度优先遍历,找出离源点距离最远的点d

step2:以d为源点,进行一次广度优先遍历,找出离d最远的点,并记录其长度


三、代码

//用邻接表实现图的转置#include <iostream>#include <queue>using namespace std;#define N 8#define WHITE 0#define GRAY 1//边结点结构struct Edge{int start;//有向图的起点int end;//有向图的终点Edge *next;//指向同一个起点的下一条边Edge(int s, int e):start(s),end(e),next(NULL){}};//顶点结点结构struct Vertex{Edge *head;//指向以该顶点为起点的下一条边bool color;//颜色,我觉得两种颜色就够了Vertex *p;//指向遍历结果的父结点int d;//与源点之间的距离Vertex():head(NULL),color(WHITE),p(NULL),d(0x7fffffff){}};//图结构struct Graph{Vertex *V[N+1];//N个顶点Graph(){int i;for(i = 1; i <= N; i++)V[i] = new Vertex;}~Graph(){int i;for(i = 1; i <= N; i++)delete V[i];}};//广搜的先进先出用STL中的队列来实现queue<Vertex*> Q;//插入边void InsertEdge(Graph *G, Edge *E){//如果没有相同起点的边if(G->V[E->start]->head == NULL)G->V[E->start]->head =E;//如果有,加入到链表中,递增顺序排列,便于查重else{//链表的插入,不解释Edge *e1 = G->V[E->start]->head, *e2 = e1;while(e1 && e1->end < E->end){e2 = e1;e1 = e1->next;}if(e1 && e1->end == E->end)return;if(e1 == e2){E->next = e1;G->V[E->start]->head =E;}else{e2->next = E;E->next = e1;}}}//在广度优先搜索的同时,记录从离源点最远的点及其长度void BFS(Graph *G, Vertex *s, int &ls, int &lv){int i;//虽然所有结点在构造函数中初始化过了,但是如果对同一图多次搜索,每次都要重新初始化for(i = 1; i <= N; i++){G->V[i]->color = WHITE;G->V[i]->d = 0x7fffffff;G->V[i]->p = NULL;}//对s进行特殊的初始化s->color = GRAY;s->d = 0;s->p = NULL;//初始化队列,使其仅含源顶点swhile(!Q.empty())Q.pop();Q.push(s);//只要队列中还有灰色顶点,循环将一直进行下去while(!Q.empty()){//确定队列头部的灰色顶点u,将其从队列中去掉Vertex *u = Q.front();Q.pop();//考察u的邻接表中每条边的终点vEdge *e = u->head;while(e){Vertex *v = G->V[e->end];//如果v是白色的,表明该顶点尚未被发现if(v->color == WHITE){//置为灰色v->color = GRAY;//计算距离v->d = u->d + 1;if(v->d > ls){ls = v->d;lv = v->id;}//u被标记为该顶点的父母v->p = u;//将它置于队列的尾部Q.push(v);}e = e->next;}//当u的邻接表中的所有顶点被检查完后,u被置为黑色(仅仅是便于理解,没有实际意义)u->color = GRAY;}}//输出void Print(Graph *G){int i;//遍历每个顶点for(i = 1; i <= N; i++){cout<<i<<':';//输出以i为起点的边的终点Edge *e = G->V[i]->head;while(e){cout<<e->end<<' ';e = e->next;}cout<<endl;}cout<<endl;}/*1 21 44 22 55 43 63 56 6*//*1 21 52 66 37 63 73 44 87 87 4*/int main(){//构造一个空的图Graph *G = new Graph;Edge *E;Print(G);//输入边int i, start, end;for(i = 1; i <= 10; i++){cin>>start>>end;E = new Edge(start, end);InsertEdge(G, E);//无向图,要加两条边E = new Edge(end, start);InsertEdge(G, E);}Print(G);int ls = -1, lv;//第一次搜索,从任意结点出发,找出最远的点lv,lv一定是所求路径上的一个端点BFS(G, G->V[1], ls, lv);ls = -1;//第二次搜索,从lv出发,找出最长的路径BFS(G, G->V[lv], ls, lv);cout<<ls<<endl;return 0;}


 

原创粉丝点击