数据结构——求邻接矩阵表示的图的关节点

#include <iostream>
using namespace std;

#include
<stdio.h>
#include
<stdlib.h>

#define OK 1
#define NULL 0
#define MAX_VERTEX_NUM 20 // 最大顶点数
//全局变量
int count;
int visited[MAX_VERTEX_NUM]; //记录节点访问的顺序
int low[MAX_VERTEX_NUM];

typedef
char VertexType;
typedef
int VRType;
typedef
int InforType;

typedef
struct ArcNode
{
int adjvex; //该边所指的顶点的位置
struct ArcNode *nextarc; //指向下一条边的指针
int weight; //边的权
}ArcNode; //表的结点

typedef
struct VNode
{
VertexType data;
//顶点信息(如数据等)
ArcNode *firstarc; //指向第一条依附该顶点的边的弧指针
}VNode, AdjList[MAX_VERTEX_NUM]; //头结点

typedef
struct ALGraph
{
AdjList vertices;
int vexnum, arcnum; //图的当前顶点数和弧数
}ALGraph;


//返回顶点v在顶点向量中的位置
int LocateVex(ALGraph &G, char v)
{
int i;
for(i = 0; v != G.vertices[i].data && i < G.vexnum; i++)
;
if(i >= G.vexnum)
return -1;
return i;
}

//增加节点
void add_vex(ALGraph &G)
{
cout
<<"输入无向图顶点数: "<<endl;
cin
>>G.vexnum;
//getchar(); //吃回车
cout<<"输入顶点信息:"<<endl;
for(int i = 0; i < G.vexnum; i++)
{
cin
>>G.vertices[i].data; //构造顶点向量
G.vertices[i].firstarc = NULL;
//getchar();
}
}

//增加边
void add_arc(ALGraph &G)
{
ArcNode
*s, *t;
ArcNode
*p;

cout
<<"输入无向图边数: "<<endl;
cin
>>G.arcnum;
char v1, v2;
cout
<<"输入边信息:"<<endl;
for(int k = 0; k < G.arcnum; k++)
{
cin
>>v1>>v2;
int i = LocateVex(G, v1);
int j = LocateVex(G, v2); //确定v1 , v2在G中的位置

s
= (ArcNode*) malloc (sizeof(ArcNode));
t
= (ArcNode*) malloc (sizeof(ArcNode));

s
->adjvex = j; //该边所指向的顶点的位置为j
s->nextarc = NULL;
if(!G.vertices[i].firstarc)
{
G.vertices[i].firstarc
=s;
}
else
{
for(p = G.vertices[i].firstarc; p->nextarc; p = p->nextarc)
;
p
->nextarc=s;
}

t
->adjvex = i; //该边所指向的顶点的位置为j
t->nextarc = NULL;
if(!G.vertices[j].firstarc)
{
G.vertices[j].firstarc
=t;
}
else
{
for(p = G.vertices[j].firstarc; p->nextarc; p = p->nextarc)
;
p
->nextarc=t;
}
}
}
//构造邻接链表
void CreateUDN(ALGraph &G)
{
add_vex(G);
//增加节点
add_arc(G); //增加边
}

void PrintAdjList(ALGraph &G)
{
int i;
ArcNode
*p;
cout
<<"编号 顶点 邻点编号"<<endl;

for(i = 0; i < G.vexnum; i++)
{
cout
<<" "<<i<<" "<<G.vertices[i].data<<" ";
for(p = G.vertices[i].firstarc; p; p = p->nextarc)
cout
<<p->adjvex<<" ";
cout
<<endl;
}
}

void DFSArticul(ALGraph &g,int v)
{
int min;
int w;
ArcNode
*q;
visited[v]
=min=++count; //记录访问次序
for(q=g.vertices[v].firstarc; q; q=q->nextarc) //对v的每个邻接点检查
{
w
=q->adjvex; //w为v的邻接顶点
if(0 == visited[w]) //w未曾访问,是v的孩子节点
{
DFSArticul(g,w);
//返回前求得low[w]
if(low[w] < min)
min
=low[w];


if(low[w] >= visited[v])
cout
<<g.vertices[v].data<<" "<<endl;
//如果low[w] >= visited[v]的话,说明v的子树上没有到v的祖先的回边,
//因为如果有回边的话,low[w]肯定就等于有回边的这个点的所有邻接点的visited[i]的最小值
//而这个点因为是v的祖先,所有这个值必然小于visited[v]
}
else if(visited[w] < min) //w已经访问,是v的祖先
{
min
= visited[w];
}
}
//for
low[v] = min;
}
//DFSArticul
//找关节点
void FindArticul(ALGraph &g)
{
//定义的全局变量见前面
count=1;
visited[
0]=1; //设定邻接表上0号顶点为生成树的根
for(int i=1; i<g.vexnum; i++)
visited[i]
=0; //其余节点尚未访问
ArcNode *p;
p
=g.vertices[0].firstarc;
DFSArticul(g,p
->adjvex); //从p的第一个邻接点出发深度优先查找关节点

if(count<g.vexnum) //生成树的根至少有两棵子树,只判断起始的根节点
{
cout
<<g.vertices[0].data<<" "<<endl;
while(p->nextarc) //对根的其它子树上的节点做判断
{
p
=p->nextarc;
if(0 == visited[p->adjvex])
DFSArticul(g,p
->adjvex);
}
//while
}//if
}//FindArticul

int main()
{
ALGraph G;
CreateUDN(G);
PrintAdjList(G);

//找关节点
FindArticul(G);
return 0;
}

 

posted @ 2010-08-07 14:20  忧国忧铭  Views(1985)  Comments(2Edit  收藏  举报