代码改变世界

第六章小结

2019-05-19 23:40  shinyshiny  阅读(231)  评论(1编辑  收藏  举报

经过两周学习,我学习了数据结构中的图这一数据结构。

在图结构中,节点之间的关系可以是任意的,途中任意两个数据元素之间都可能相关。由此,图的应用极为广泛。

学习中,重点需要掌握的部分是图的邻接矩阵和邻接表两个储存结构和基于这两种结构的遍历,深度优先遍历和广度优先遍历,以及图的应用-最小生成树。

而这次的题目主要与两种遍历有关

以下是题目内容:

 

列出连通集

给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。

输入格式:

输入第1行给出2个整数N(0)和E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。

输出格式:

按照"{ v1​​ v2​​ ... vk​​ }"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。

输入样例:

8 6
0 7
0 1
2 0
4 1
2 4
3 5

输出样例:

{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }

题目本质其实是非连通图的遍历
所以解题思路非常简单,我使用了邻接矩阵的储存结构来储存这个图,然后就是基于邻接矩阵的深度优先遍历和广度优先遍历,因为是非连通图,所以需要在主函数中多次调用DFS算法和BFS算法即可解决非连通图的问题。
以下是解决的代码。
#include<iostream>
#include<queue>
using namespace std;

const int mvnum=100;

typedef struct{
    int arcs[mvnum][mvnum];
    int vexnum,arcnum;
}AMGraph;

bool visited[mvnum]={false};

bool Visited[mvnum]={false};

int vexs[mvnum];

int LocateVex(AMGraph G, char u)
 {//存在则返回u在顶点表中的下标;否则返回-1
   int i;
   for(i=0; i<G.vexnum; ++i)
     if(u==vexs[i])
       return i;
   return -1;
 }
 
void CreateUDN(AMGraph &G){
    int i,j,k,v1,v2;
  cin>>G.vexnum>>G.arcnum; //输入总顶点数,总边数 
  for(i=0; i<G.vexnum; ++i)
  //初始化邻接矩阵,边的权值均置为0
      for(j=0; j<G.vexnum;++j)   
         G.arcs[i][j] = 0;   
  for(int k=0; k<G.arcnum; ++k){   //构造邻接矩阵 
      cin>>v1>>v2; //输入一条边依附的顶点
      i = LocateVex(G, v1);  
      j = LocateVex(G, v2);//确定v1和v2在G中的位置
      G.arcs[i][j] = 1; //边<v1, v2>置为1 
      //<v1, v2>的对称边<v2, v1>也置为1 
      G.arcs[j][i] = G.arcs[i][j];  
   }
}

 
 void DFS_AM(AMGraph G, int v)
{  //图G为邻接矩阵类型 
  cout<<v<<" ";  //访问第v个顶点
  visited[v] = true;
  for(int w=0; w<G.vexnum; w++) //依次检查邻接矩阵v所在的行  
     if((G.arcs[v][w]!=0)&& (!visited[w]))  
         DFS_AM(G, w); //w是v的邻接点,如果w未访问,则递归调用DFS_AM 
}

int FirstAdjVex(AMGraph G,int u)
{
    //查找与数组下标为v的顶点之间有边的顶点,返回它在数组中的下标
    for(int i = 0; i<G.vexnum; i++){
        if( G.arcs[u][i]!=0){
            return i;
        }
    }
    return -1;
}
int NextAdjVex(AMGraph G,int u,int w)
{
    //从前一个访问位置w的下一个位置开始,查找之间有边的顶点
    for(int i = w+1; i<G.vexnum; i++){
        if(G.arcs[u][i] != 0){
            return i;
        }
    }
    return -1;
}

void BFS (AMGraph G, int v)
{ //按广度优先非递归遍历连通图G 
    int u;
    cout<<v<<" "; Visited[v] = true;
    queue<int> q;    //辅助队列Q初始化,置空         
    q.push(v);  //v进队 
    while(!q.empty()){ //队列非空 
     u = q.front(); //队头元素出队并置为u 
       q.pop();
        for(int w = FirstAdjVex(G, u); w>=0; w = NextAdjVex(G, u, w)) 
         if(!Visited[w]){//w为u尚未访问的邻接顶点 
             cout<<w<<" ";    Visited[w] = true;
             q.push(w);  //w进队 
          }
    }
}


int main()
{
    for(int i=0;i<mvnum;i++)
    {
        vexs[i]=i;
    }
    AMGraph g;
    CreateUDN(g);
    int v=0,x=0;
    for(v;v<g.vexnum;v++)
    {
        if(!visited[v]){
        cout<<"{ ";
        DFS_AM(g,v);
        cout<<"}";
        cout<<endl;
    }
    }
    for(x;x<g.vexnum;x++)
    {
        if(!Visited[x]){
        cout<<"{ ";
        BFS(g,x);
        cout<<"}";
        cout<<endl;
    }
    }
    return 0;
}
View Code