c语言之图的定义及遍历

来源:互联网 发布:jenkins php docker 编辑:程序博客网 时间:2024/06/05 00:52
图的两种存储方式

一、邻接矩阵:
邻接矩阵的结构定义
typedef struct
{
int no;                    //顶点编号
char info;              //存储顶点的其他信息
}VertexType;

typedef struct                                            //图的定义
{
int edges[maxsize][maxsize];                 //定义二维数组存储边的关系
int n,e; //存储顶点数和边数
VertexType vex[maxsize];                 //存储节点信息
}MGraph;
二、邻接表的结构定义
typedef struct AcNode
{
int adjvex;
struct AcNode *nextarc;
}AcNode;                       //定义链表的节点
typedef struct VNode
{
int data;
struct VNode *firstAcNode;
}VNode;                      //定义顶点
typedef struct 
{
VNode adjlist[maxsize];
int n,e;
}AGraph;

///////////////////////////////////////////////////////////////////////////////////////////////////////////
图的深度优先遍历
(以邻接表为存储结构)
int visit[maxsize];             //存储节点访问信息,初始化为0。因图中可能存在环路,当前节点将来可能再次经过,因此要对每个顶点进行标记,以免重复访问
void DFS(AGraph *G, int v)
{
AcNode *p;
visit[v] = 1;
  Visit(v);                        //Visit函数代表一类访问顶点v操作
  p = G->adjlist[v].firstAcNode;
  while(p != NULL)
  {
  if(visit[p->adjvex] == 0)                //若为被访问,则递归访问
  DFS(G,p->adjvex);
  p = p->nextarc;
  }
}

图的广度优先遍历(需要借助队列实现)
(以邻接表为存储结构)
void BFS(AGraph G, int v, int visit[maxsize])
{
AcNode *p;
int que[maxsize],front = 0,rear = 0;
int j;
Visit(v);  //Visit函数代表一类访问顶点v操作
visit[v] = 1;
rear = (rear+1)%maxsize;           //当前节点进队
que[rear] = v;
while(front != rear)
{
front = (front+1)%maxsize;   //顶点出队
j = que[front];
p = G->adjlist[j].firstAcNode;
while(p != NULL)
{
if(visit[p->adjvex] == 0)
{
Visit(p->adjvex);
visit[p->adjvex] = 1;
rear = (rear+1)%maxsize;         //该顶点进队
que[rear] = p->adjvex;
}
p = p->nextarc;

}
}


例题1:
设计算法,求不带权无向连通图图G中距离顶点v最远的一个顶点(最远是指到达v路径长度最长)
分析:图的广度优先搜索遍历方式体现由图中某个顶点开始,以由近向远层层扩展的方式遍历图中节点的过程。及最后遍历节点即为最远节点


int BFS(AGraph *G, int v)
{
AcNode *p;
int que[maxsize],front = 0,rear = 0;
int j;
int visit[maxsize] = 0;           //初始化为0
visit[v] = 1;
rear = (rear+1)%maxsize;           //当前节点进队
que[rear] = v;
while(front != rear)
{
front = (front+1)%maxsize;   //顶点出队
j = que[front];
p = G->adjlist[j].firstAcNode;
while(p != NULL)
{
if(visit[p->adjvex] == 0)
{
visit[p->adjvex] = 1;
rear = (rear+1)%maxsize;         //该顶点进队
que[rear] = p->adjvex;
}
p = p->nextarc;

}
return j;
}


例题2:
设计算法,判断无向图G是否是一棵树。若是返回1,否则返回0
分析:一个无向图是一棵树的条件是有n-1 条边的连通图,n为图中顶点个数。边和顶点的数目是否满足条件可由图的信息直接判断,连通与否可以用遍历能否访问到所有顶点来判断。

void DFS(AGraph *G, int v, int &vn, int &en)
{
AcNode *p;
visit[v] = 1;
++vn;
p = G->adjlist[v].firstAcNode;
while(p != NULL)
{
++en;
if(visit[p->adjvex] == 0)
DFS(G,p->adjvex,vn,en);
p = p->nextarc;
}
}

int GisTree(AGraph *G)
{
int vn = 0, en = 0;
int i;
for(i = 1; i <= G->n; ++i)
visit[i] = 0;
DFS(G, 1, vn, en);
if(vn == G->n && (G->n-1) == en/2)
//如果遍历过程中访问过的顶点和图中顶点数相等,且边数等于顶点数减1,即证明是树
return 1;
else
return 0;
}