2020-5-21-图(邻接表邻接矩阵)DFS,BFS

图的基本概率:

  1. 点集 V(vertexs)和边集 E(edges)组成

  2. 有向图和无向图

  3. 弧 Arc : <vi ,vj> 

  4. 路径: 相邻顶点序偶构成的序列

  5. 路径长度: 路径上边的数目

图的存储结构:

  1. 邻接矩阵(顺序存储结构,无向图是对称的)

  2. 邻接表(链式存储结构)

 

代码实现:

1: 邻接矩阵 (DFS ,BFS遍历)

2: 邻接表    ( DFS ,BFS遍历)

 

1: 邻接矩阵(DFS ,BFS遍历)

​/*
 编制日期:2020-5-20
 图的存储:邻接矩阵
 图的遍历:1:DFS   2:BFS
​
*/
​
#include <iostream>
#include<cstring>
using namespace std ;
#define MaxSize 50      //图最大顶点个数
#define inf 999999999  //无穷大值,在图中表示不连通
typedef  int  datatype; //可以根据需要改变数据类型,也可以自己封装数据类型
//邻接矩阵
typedef struct{
    int num;    //顶点编号
    char info;  //顶点信息
}Node ; // 顶点类型
typedef struct{
  datatype edgs[MaxSize][MaxSize] ; //保存图的,边集权重信息
  int n,e ;   // n 顶点的总数, e 边数
  Node nodes[MaxSize] ; //保存顶点信息
}MGraph;
int visited[MaxSize] ;   //访问记录数组
/*  构造图的初始函数 */
MGraph InitiaL_Graph(){
    MGraph graph ;
    int n ,e ;
    int i, j ;
    cout<<"初始化图操作:请输入你要构造的图的 顶点数(n) 和边数(e)"<<endl ;
    cout<<"请输入n: \t";
    cin>>n;
    cout<<"请输入e:\t";
    cin>>e;
    graph.n = n ;
    graph.e = e ;
    for(i=1;i<=n;i++ ){
        for(j=1;j<=n;j++){
            if(i == j)
                graph.edgs[i][i] = 0 ; //同一点距离为 0
            else
            graph.edgs[i][j] =inf ; 把每条边赋值无穷大,表示不连通
        }
    }
    cout<<"请输入边值权重"<<endl ;
    cout<<" edgs[i][j] = weight,如果没有图中没有weight,请全输入1占位: 输入格式 i ,j ,weight"<<endl ;
    i= 1 ;
    j=1;
    while(e--){
        datatype temp ;
        cin>>i>>j>>temp ;
        graph.edgs[i][j] = temp ;
    }
    return graph ;
}
/*  处理函数,根据实际需要编写 */
void process(MGraph graph , int v)
{
    cout<<v<<" " ; //打印遍历结点
}
/* DFS基本思想 :
​
    步骤1:访问出发点 V,然后标记已经访问过,然后选取V,邻接的未被访问的任意一个结点 i 访问
    步骤2:对结点i ,重复步骤1
​
*/
void DFS(MGraph graph, int v)
{
    int i ;
    //步骤1
    visited[v] = 1 ; //标记已经访问
    process(graph,v) ; //对结点v的操作
    for(i =1;i<=graph.n ;i++){
        if(graph.edgs[v][i]!=inf && visited[i]==0&&graph.edgs[v][i]!=0){ //注意条件,edges[v][i]这条边必须存在,和结点i没有被访问过,visited[i] =0
            //步骤2
            visited[i] =1 ;   //i 结点表示访问
            DFS(graph,i);     //继续向前搜索
        }
    }
}
/* BFS基本思想:
    步骤1:访问初始点v ,接着访问与v结点邻接的所有结点 j1,j2,....jn
    步骤2:然后接着,依次访问j1,j2,....jn 邻接的所有结点(访问的结点除外)
    算法实现借助队列
*/
void BFS(MGraph graph ,int v)
{
    int  Queue[MaxSize] ,Front=0,Rear = 0 ;
    int i ;
    //步骤1
    visited[v] = 1 ;
    process(graph,v) ; //对结点v 的操作
    Rear =(Rear+1) %MaxSize ;
    Queue[Rear] = v ;
    //步骤2:
    while(Front != Rear){
        Front = (Front +1) %MaxSize ;
        i = Queue[Front] ; //将当前没有访问i 结点的邻接点入队
        for(int j = 1 ;j<=graph.n;j++){
            if(visited[j]==0 && graph.edgs[i][j]!=inf && graph.edgs[i][j]!=0){
                process(graph,j);
                visited[j]=1 ;
                Rear =(Rear+1)%MaxSize ;
                Queue[Rear] = j ;
            }
        }
​
    }
}
int main()
{
   int i ;
   MGraph graph = InitiaL_Graph() ;
   memset(visited,0,sizeof(visited)) ; //标记数组全置为0
   cout<<"图的邻接矩阵如下:"<<endl ;
   for(i=1 ;i<=graph.n ;i++){
     for (int j=1 ;j<=graph.n;j++)
        cout<<graph.edgs[i][j]<<" ";
    cout<<endl ;
   }
   for(i= 1 ;i<=graph.n;i++)
     visited[i] = 0 ;
   cout<<"图的深度优先搜索遍历: DFS"<<endl ;
   for(i = 1 ; i<=graph.n ;i++){
     if(visited[i]==0){
        DFS(graph ,i) ;
     }
   }
   cout<<endl ;
   cout<<"图的广度优先搜索遍历: BFS"<<endl ;
   memset(visited,0,sizeof(visited)) ; //标记数组全置为0
   for(i= 1 ;i<=graph.n;i++)
     visited[i] = 0 ;
   for(i = 1 ; i<=graph.n ;i++){
     if(visited[i]==0){
        BFS(graph ,i) ;
     }
   }
   cout<<endl ;
  return (1) ;
}
/*
输入 n =5 ,e =5
图:
1 2 1
1 3 1
1 5 1
2 4 1
5 4 1
*/

2: 邻接表    ( DFS ,BFS遍历)

/*
 编制日期: 2020-5-21
 图的存储:  邻接表
 图的遍历:  1:DFS   2:BFS
*/
​
#include <iostream>
#include<cstring>
using namespace std ;
#define MaxSize 50      //图最大顶点个数
#define inf 999999999  //无穷大值,在图中表示不连通
typedef  int  datatype; //可以根据需要改变数据类型,也可以自己封装数据类型
//邻接表
typedef struct ArcNode{
    int adjvex;        //该边指向的顶点编号,(邻接点编号)
    ArcNode *next ;    //指向下一条边的指针
    datatype info;     //边的信息,可以是权重
}ArcNode ;             //一个弧结点
typedef struct{
    int  num ;          // 顶点编号信息
    ArcNode *firstArc ; // 指向第一条边的指针
}VNode ;                //结点
typedef struct{
  int n,e ;                 // n 图顶点的总数, e 边数
  VNode adjList[MaxSize] ;  //各节点邻接表(一个节点一条链表,链表中元素为邻接边顶点adjvex,和边上info)
}AGraph;
int visited[MaxSize] ;      //访问记录数组
/*  构造图的初始函数  */
AGraph* InitiaL_Graph(){
    AGraph *graph ;
    int n ,e ;     // n ,这个图的顶点个数,e 变数
    int i;
    graph = new AGraph ;  //开辟一个图存储空间,不然有空指针异常
    cout<<"初始化图操作:    请输入你要构造的图的 顶点数(n) 和边数(e)"<<endl ;
    cout<<"请输入总的顶点数: n \t";
    cin>>n;
    cout<<"请输入总的变数: e:  \t";
    cin>>e;
    graph->n = n ;
    graph->e = e ;
    cout<<"请输入各个顶点的邻接边:\tadjvex: 顶点编号\t weight: 边值权重,没有输入1占位  "<<endl ;
    i =1 ;
    while(i<=n){
        VNode   *vnodei ;                    //节点邻接链
        ArcNode *arcNodeHead,*temp_arnode;    //节点链表,采用尾插法,temp_arcnode ,是临时结点,arcNodeHead是链表头
​
        vnodei = new VNode ;        //分配地址,不然有空指针异常
        arcNodeHead = new ArcNode;
        arcNodeHead->next =NULL;     //初始化链表
        arcNodeHead->adjvex=i ;      //第一个邻接点,指向自己,这条语句可以不要
        temp_arnode = arcNodeHead ;
​
        while(true){
          int node_num ;            //邻结点编号
          datatype nodeWeight ;     //邻结点这条边的(info) 测试采用的权重
          ArcNode *temp;           //临时保存一条邻接边的信息
          cout<<"第"<<i<<"个结点的邻接链表,格式:邻结点的: 编号  权重(没有输入1占位), 输入 -1 0 结束"<<endl ;
          cin>>node_num>>nodeWeight ;
          if(node_num==-1){
                temp_arnode->next =NULL ;
                break ;
         }
          temp = new ArcNode ;
          temp->adjvex = node_num ;
          temp->info  = nodeWeight ;
​
          temp_arnode->next = temp ; //将邻接边加入链表中,尾插法
          temp_arnode = temp ; //指针后移动
      }
      temp_arnode->next=NULL ;          //链表尾置为空
      vnodei->firstArc =arcNodeHead->next  ;  //应为第一个结点没有保存领接边信息,后移1位
      vnodei->num = i ; //标记为i结的邻接边
      graph->adjList[i] = *vnodei; //添加到图的邻接表中
       i++ ;  //下一个结点
    }
    return graph ;
}
/*  处理函数,根据实际需要编写   */
void process(AGraph *graph , int v)
{
    cout<<v<<" " ; //打印遍历结点
}
/* DFS基本思想 :
    步骤1:  访问出发点 V,然后标记已经访问过,然后选取V,邻接的未被访问的任意一个结点 i 访问
    步骤2:  对结点i ,重复步骤1
*/
void DFS(AGraph *graph,int v)
{
    ArcNode *p ;
    //步骤1
    visited[v] =1 ;
    process(graph ,v) ;
    p = graph->adjList[v].firstArc ; //结点v的邻接边链
    //步骤2
    while(p!=NULL){
        if(visited[p->adjvex]==0){
            DFS(graph,p->adjvex); //继续向前搜索
        }
       p=p->next ;  //下一个邻接点
    }
​
}
void PrintAdj(AGraph *graph)
{
  int i,n,num ;
  n = graph->n ; //图的变数
  for(i=1;i<=n;i++){
    ArcNode *p ;
    num = graph->adjList[i].num ; //结点i编号
    p= graph->adjList[i].firstArc ; //结点i的邻结点链
    cout<<num<<" ->";
    while(p){
        cout<<p->adjvex<<"->" ; //邻结点编号
        p=p->next ;
    }
    cout<<endl ;
  }
}
/* BFS基本思想:
    步骤1: 访问初始点v ,接着访问与v结点邻接的所有结点 j1,j2,....jn
    步骤2: 然后接着,依次访问j1,j2,....jn 邻接的所有结点(访问的结点除外)
    算法实现借助队列
*/
void BFS(AGraph *graph , int v)
{
    ArcNode *p ;
    int Queue[MaxSize] ,Front=0 ,Rear=0 ;
    int i ;
    //步骤1
    process(graph ,v);  //对结点v 的操作
    visited[v] = 1 ;    //标记结点v访问
    Rear =(Rear + 1)%MaxSize ;
    Queue[Rear] = v ;   //结点v进队
    //步骤2
    while(Rear != Front){
        Front =(Front +1 )%MaxSize ;
        i = Queue[Front] ;
        p = graph->adjList[i].firstArc ; //第一个邻结点
        while(p!=NULL){
             if(visited[p->adjvex]==0){  //邻接点没被访问
                process(graph,p->adjvex) ;  //对邻结点操作
                visited[p->adjvex] =1 ;   //标记这个结点访问
                Rear = (Rear+1)%MaxSize ;  //进队
                Queue[Rear] = p->adjvex ;
             }
             p= p->next ;    //下一个邻结点
        }
    }
}
​
int main()
{
   int i ,n ;
   AGraph *graph = InitiaL_Graph() ; //图的初始化
   //打印图的邻接表
   cout<<"邻接表"<<endl ;
   PrintAdj(graph);
   n = graph->n ;  //图的表数
   memset(visited,0,sizeof(visited)) ; //清0
   for(i=1;i<=n;i++)
    visited[i] =0 ;   // 0 表示未被访问  1表示访问
   cout<<"深度优先搜索遍历"<<endl ;
   for(int i=1;i<=graph->n;i++){
     if(visited[i]==0)
        DFS(graph,i) ;
   }
   cout<<endl ;
   memset(visited,0,sizeof(visited)) ;
   for(i=1;i<=n;i++)
    visited[i] =0 ;
    cout<<"广度优先搜索遍历"<<endl ;
    for(int i=1;i<=graph->n;i++){
     if(visited[i]==0)
     BFS(graph,i) ;
   }
  return (1) ;
}
​
​
/*
输入 n = 5 e= 7
i=1 : 
    2 1
    4 1
    5 1
    -1 0
i=2 :
    5 1
    3 1
    -1 0
i=3: 
    1 1
    -1 0
i=4:
    3 1
    -1 0
i=5: 
    -1 0
end 
*/

                
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值