构造图(存储结构)

利用邻接矩阵

- 邻接矩阵——优点?

    • 直观、简单、好理解
    • 方便检查任意一对顶点间是否存在边
    • 方便找任一顶点的所有“邻接点”(有边直接相连的顶点)
    • 方便计算任一顶点的“度”

- 缺点:

    • 不便于增加和删除顶点
    • 浪费空间
    • 浪费时间(需要统计有多少边)

代码

#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;
#define MVNum 100
#define MaxInt 32767//极大值
typedef struct//最大顶点数
{
    int vexs[MVNum];//顶点表
    int arcs[MVNum][MVNum];//邻接矩阵
    int vexnum,arcnum;//图当前点数和边数
}AMGraph;


int LocateVex(AMGraph G,int u)
{
    int i;
    for(i=0;i<G.vexnum;i++)
    {
        if(u==G.vexs[i])  return i;
    }
    return -1;
}
//构造无向网
/*
无向图:
       1.初始化邻接矩阵时,w均为0;
       2.构造邻接矩阵时,w为1;
       ///或直接去掉权值w

有向网:
       (因为邻接矩阵为非对称矩阵,)
       仅向G.arc[i][j]赋值,不向G.arcs[j][i]赋值即可
有向图:
       ..........
*/
//初始化邻接矩阵
void Created(AMGraph &G)
{
     cin>>G.vexnum>>G.arcnum;
    int i;int j;
    for(i=0;i<G.vexnum;i++)
    {
        cin>>G.vexs[i];
    }
    for(i=0;i<G.vexnum;i++)
    {
        for(j=0;j<G.arcnum;j++)
        {
            G.arcs[i][j]=MaxInt;
        }
    }
    int v1,v2,w;

    int k;
    for(k=0;k<G.arcnum;k++)//构造邻接矩阵
    {
        cin>>v1>>v2>>w;//输入一条边的两顶点和权值
        i=LocateVex(G,v1);
        j=LocateVex(G,v2);
       G.arcs[j][i]=G.arcs[i][j]=w;
    }
}


int main()
{
    AMGraph G;
    Created(G);


return 0;
}

利用邻接表

特点

- 对于无向图

    • 邻接表不唯一
    • 无向图有n个顶点,e条边,则邻接表需要n个头结点,2e个表节点.
    • 适宜稀疏图

- 对于有向图

    • 找出度易:顶点v(i)的出度为第i个单链表中的结点个数。
    • 找出度难:需要全部遍历,顶点V的入度为整个单链表中邻接点域值是i-1的结点个数
    • 可以使用逆邻接表,则找出入度易,找出度难

代码

#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<iostream>
using namespace std;
#define MVNum 100 //容量
#define MaxInt 32767//极大值

//弧(边)的结点定义
typedef struct ArcNode
{
    int adjvex;//该边所指向的顶点的位置
    struct ArcNode *nextarc;//指向下一条边的指针
//    Otherlnfo info;//和边相关的其他信息
}
ArcNode;

//顶点结构体
typedef struct VNode
{
    int data;//顶点信息
    ArcNode *firstarc;//指向第一条边的指针
}
VNode,AdjList[MVNum];//AdjList表示邻接表类型
/*
说明:AdjList v 等价于 VNode v[MVNum];
*/

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


int LocateVex(ALGraph G,int k)
{
    int i;
    for(i=0;i<G.arcnum;i++)
    {
        if(G.vertices[i].data == k) return i;
    }
    return -1;
}
//采用邻接法表示法,创建无向网G
void CreateUDG (ALGraph &G)
{
    cin>>G.vexnum>>G.arcnum;//输入总顶点,总边数

    int i,j;
    for(i=0;i<G.vexnum ;i++)//建立表头节点表
    {
        cin>>G.vertices[i].data;//顶点值
        G.vertices[i].firstarc=NULL;//初始化指向的边
    }
    int v1,v2,k;
    for(k=0;k<G.arcnum ;k++)//输入边,构造邻接表
    {
        cin>>v1>>v2;//输入边,依附的两个顶点
        i=LocateVex(G,v1);//查找到顶点1位置
        j=LocateVex(G,v2);//查找到顶点2位置

       ArcNode *p1 = new ArcNode;//生成新的边结点
        p1->adjvex = j;//邻接序号为j;
        p1 -> nextarc = G.vertices[i].firstarc;
        G.vertices[i].firstarc=p1;//头插进顶点d边表头部
        
         ArcNode *p2 = new ArcNode;
        p1->adjvex =i;
        p1 -> nextarc = G.vertices[j].firstarc;
        G.vertices[j].firstarc=p1;
    }
}
int main()
{
    ALGraph G;


return 0;
}


区别邻接矩阵和邻接表

image
用途
邻接矩阵用于稠密图,邻接表用于稀疏图
联系

  • 联系:邻接表中每个链表对应于邻接矩阵中的一行,链表中结点个数等于一行中非零元素的个数。
    区别
  • 对于任一确定的无向图,邻接矩阵是唯一的(行列号与顶点编号一
    致),
    • 但邻接表不唯一(链接次序与顶点编号无关)。
  • 邻接矩阵的空间复杂度为O(n的2次幂),
    • 而邻接表的空间复杂度为o(n+e)。

十字链表和临接多重表

十字链表(用于有向图)

解决:邻接表求结点的度困难
方法:

  • 顶点结点,增加一个指向 入度的指针
  • 边结点,增加 入度顶点信息,
    image

临接多重表(用于无向图)

解决:邻接表的而

实战

存储

邻接矩阵构建

//用c语言写,c++会超时

#include<stdio.h>
#include<iostream>
#include <string.h>
#include <stdbool.h>

using namespace std;
      bool a[5005][5005];
int main()
{
    int n,m, i, u,v, x,y, q;
  while(scanf("%d %d",&n,&m)!=EOF)
  {
      memset(a,0,sizeof(a));

        for(i=0; i<m; i++)
        {
            cin>>u>>v;
            a[u][v]=1;
        }

        cin>>q;

        for(i=0; i<q; i++)
        {
            cin>>x>>y;
            if(a[x][y]==1)
                cout<<"Yes"<<endl;
            else
                cout<<"No"<<endl;
        }


  }
    return 0;
}


邻接表存储

//用c语言写,c++会超时

#include<stdio.h>
#include<iostream>
#include <string.h>
#include <stdbool.h>
using namespace std;

struct node
{
    int data;
    struct node *next;
};
int main()
{
    int n,m;
   while(cin>>n>>m) 
   {
       

    int i,u,v;
    struct node *G[500001],*Q;
      for(i=0;i<n;i++)
      {
           G[i]=(struct node*)malloc(sizeof(struct node));
          G[i]->next=NULL;
          G[i]->data=-1;
      }

    for(i=0;i<m;i++)
    {
       cin>>u>>v;
       Q=(struct node*)malloc(sizeof(struct node));
       Q->data=v;
       Q->next=G[u]->next;
       G[u]->next=Q;
    }

    int p;
    cin>>p;

    int a,b;
    for(i=0;i<p;i++)
    {
       cin>>a>>b;
       Q=G[a];

    while(Q!=NULL)
       {


           if(Q->data==b)
           {
               cout<<"Yes"<<endl;
               break;
           }
           Q=Q->next;
       }
       if(Q==NULL)
       {
           cout <<"No"<<endl;
       }
    }

   }
 return 0;
}
### [图的基本存储的基本方式三](https://acm.sdut.edu.cn/onlinejudge3/problems/3118 "图的基本存储的基本方式三")
#include<stdio.h>
#include<iostream>
#include <string.h>
#include <stdbool.h>
using namespace std;

typedef struct
{
    int a=0;
    int b=0;
    int c=0;

}TU;


void q_sort(TU a[],int l,int r)//快速排序
{

    TU key=a[l];
    int i=l;
    int j=r;
    if(l>=r)
        return;
    while(i<j)
    {//权值w小的在前;
    //权值相等时出发点u小的在前;
    //权值和出发点相等时到达点v小的在前
        while(i<j &&(key.c<a[j].c
        ||(key.c==a[j].c&&key.a<a[j].a)
        ||(key.c==a[j].c&&key.a==a[j].a&&key.b<a[j].b)))
            j--;
        a[i]=a[j];

         while(i<j&&(key.c>a[i].c
        ||(key.c==a[i].c&&key.a>a[i].a)
        ||(key.c==a[i].c&&key.a==a[i].a&&key.b>a[i].b)))
            i++;
        a[j]=a[i];
    }
    a[i]=key;
    q_sort(a,l,i-1);
    q_sort(a,i+1,r);
}
int main()
{
    int n,m;
   while(cin>>n>>m)
   {
       TU G[m];
       int i;
       for(i=0;i<m;i++)
       {
        cin>>G[i].a>>G[i].b>>G[i].c;
       }
       //sort(G.c,G.c+m);
       q_sort(G,0,m-1);



       int q;
       cin>>q;
       int k;
       for(i=0;i<q;i++)
       {
           cin>>k;
           cout<<G[k].a<<" "<<G[k].b<<endl;
       }
   }
 return 0;
}

用邻接表

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
struct node
{
    int data;
    struct node *next;
}*a[5010];
void add(int i, int j)
{
    struct node *q;
    q  = (struct node *)malloc(sizeof(struct node));
    q->data = j;
    q->next = NULL;
    if(a[i] == NULL){
        a[i] = q;
    }else {
        q->next = a[i]->next;
        a[i]->next = q;
    }
}
int main()
{
    int n;
    while(~scanf("%d", &n)){
        int i, j;
        int x;
        int u, v;
        struct node *p;
        for(i = 0;i < n;i++){
            a[i] = NULL;
        }
        for(i = 0;i < n;i++){
            for(j = 0;j < n;j++){
                scanf("%d", &x);
                if(x == 1){
                    add(i,j);
                }
            }
        }
        int q;
        scanf("%d", &q);
        int flag;
        while(q--){
            scanf("%d %d", &u, &v);
            flag = 0;
            p = a[u];
            while(p){
                if(p->data == v){
                    flag = 1;
                    break;
                }
                p = p->next;
            }
            if(flag){
                printf("Yes\n");
            }else {
                printf("No\n");
            }
        }
    }
 
    return 0;
}
posted @ 2021-08-18 21:30  kingwzun  阅读(46)  评论(0编辑  收藏  举报