二哥学算法之图(开篇)

图论问题几乎涉及整个计算机科学,成千上百的计算问题几乎都可以归纳总结为图论问题。生活中也有很多需要图论的例子,如以后为大家提到的最大二分图匹配,最小费用最大流,单源最短路径等等,我对这部分也只是略知一个,有错误之处还望大家指出。
先定义一下图:一个图(Graph)可以看做是边和点的集合。我们有G=(V,E) V(vertex)表示顶点集,E(Edge)表示边集。每一条边就是一个点对(u,v),如果一个点对是有序的,比如说只能从u到v,从v到u是 非法的;则(u,v)这条边就是有序的。反之,则有无向图。即(u,v),(v,u)都是合法的。图常常还会具有第三种属性,叫做权(weight)或值(cost)。
现在给大家介绍两种图的表示方法。邻接链表和邻接矩阵。
邻接矩阵表示起来相对来说比较简单即通过一个二维数组Array[N[N],对于每一条边(u,v),可以置Array[u[[v]=1,如果边上有权值。则可以用一个很大或者很小的值表示不存在的边。
下面是一个用邻接矩阵表示图的示例代码:

#include <iostream>
#define INIFY 66553  
#define N 8   //顶点数目
int array[N][N]
int Edge_Numbers;
int main(void){
  int i,j,k;
  std::cout<<"请输入顶点数: "<<std::endl;
  std::cin>>Edge_Numbers;
  //初始化顶点
  for(i=0;i<N;i++)
      for(j=0,j<N;j++)
          array[i][j]=INIFY;
  std::cout<<"请输入顶点关系和权值"<<std::endl;
  for(int m=0;m<Edge_Numbers;m++){
      std::cin>>i>>j>>k;
      array[i][j]=k;  
      //如果是无向图
      array[j][i]=array[i][j]=K;
      }
   return 0;
   }

用这种方法表示图很简单,不要很明显看以看出。图的空间需求为这里写图片描述,如果图的边不是很多,那么这种表示方法就有点浪费内存了。如果图是稠密的, 这里写图片描述这种方法就是很合适的。
另一方面如果图不是稠密的,换句话说如果是稀疏的,则更好的解决办法就是用上面提高的邻接链表了。对于每一个顶点,我们使用一个表来存储所有的邻接顶点。此时空间需求度为这里写图片描述。下面我写一个示例性的邻接表实现(质量很渣渣,不要模仿,仅供参考)

#include <iostream>
#define N 4
int array[N][N];

//邻接表 
struct Edge{
    int from;
    int to;
    int weight;
    Edge *next;
    Edge(int _from=-1,int _to=-1,int _weight=0):
            from(_from),to(_to),weight(_weight){
            }
};
Edge *edge[N]={nullptr,nullptr,nullptr};
void add_edge(){
    int u,v,k;
    Edge *p=nullptr;
    std::cout<<"请输入顶点i,j和k;以-2作为结束。"<<std::endl;
    while(std::cin>>u>>v>>k&&u!=-2,v!=-2){
        p=new Edge;
        p->from=u,p->to=v,p->weight=k,p->next=nullptr;
        p->next=edge[u];
        edge[u]=p;
    }
}
void print_edge(Edge *p){
    Edge *v;
    std::cout<<"和"<<p->from<<"邻接的顶点及其权重值如下: "<<std::endl;
    for(v=p;v!=nullptr;p=p->next,v=p)
        std::cout<<v->to<<" weight:"<<v->weight<<std::endl;
}
int main(void){
    add_edge();
    print_edge(edge[1]);
    return 0;
}

以上;下篇为大家带来图的BFS和DFS。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值