数据结构考研 - 图(C语言)

数据结构考研 - 图的知识点与思维导图 幕布链接

1. 存储结构

1.1 邻接矩阵(顺序表)

1.1.1 结构型定义
typedef struct
{
    int no;
    char info;
} VertexType

typedef struct
{
    int edges[maxSize][maxSize];
    int n, e;
    VertexType vex[maxSize];
} MGraph;

1.2 邻接表(链表)(很少考代码)

1.3 邻接多重表(很少考代码)

类似于十字链表

2. 遍历

2.1 深度优先遍历 DFS

void DFS(AGraph *G, int v)
{
  ArcNode *p;
  visit[v]=1;
  Visit(v);
  p=G->adjlist[v].firstarc; //p指向顶点v的第一条边
  while(p!=NULL)
  {
    if(visit[p->adjvex]==0)
      DFS(G, p->adjvex);
      p=p->nextarc; // p指向顶点v的下一条边
  }
}

2.2 广度优先遍历 BFS

void BFS(AGraph *G, int v, int visit[maxSize]) 
//注意这里的visit数组作为参数传入,与DFS不一样
// visit[] 数组初始化为0
  {
    ArcNode *;
    int que[maxSize], front = 0, rear = 0;
    int j;
    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].firstarc;
      while(p!=NULL) // 将p的所有邻接点钟未被访问的入队
      {
        if (visit[p->adjvex]==0)
        {
          Visit(p->adjvex);
          visit[p->adjvex]=1;
          rear=(rear+1)%maxSize;
          que[rear]=p->adjvex;
        }
        p = p->nextarcc;
      }
   }
}

3. 最小生成树

3.1 克鲁斯卡尔算法 Kruskal

适用于 无向图 稀疏图
这里写图片描述

//此为求的最小代价的函数,因为求生成树考的极少  
typedef struct
{
  int a,b;
  int w;
}Road;
Road road[maxSize];
int v[maxSize];      //定义查找集数组
int getRoot(int a) //定义查找集中找根结点的函数
{
  while(a!=v[a]) a=v[a];
  return a;
}
void Kruskal(MGraph g; int &sum, Road road[])
{
  int i;
  int N, E, a, b;
  N=g.n;
  E=g.e;
  sum=0;
  for(i=0;i<N;++i) v[i]=i;
  sort(road, E); //对road数组中的E条边按其权值从大到小排序
  for(i=0;i<E;++i)
  {
    a=getRoot(road[i].a)
    b=getRoot(road[i].b)
    if(a!=b)
    {
      v[a]=b;
      sum+=road[i].w;
    }
  }
}

3.2 普里姆算法 PRIM

适用于 稠密图
这里写图片描述

//此为求的最小代价的函数,因为求生成树考的极少
void Prim(MGraph g, int v0, int &sum)
{
  int lowcost[maxSize], vset[maxSize], v;
  int i,j,k,min;
  v=v0;
  for(i=0;i<g.n;++i)
  {
    lowcost[i]=g.edges[v0][i];
    vest[i]=0;
  }
  vset[v0]=1;
  sum=0;
  for(i=0;i<g.n-1;++i)
  {
    min = INF;
    // 下面这个循环用于选出候选边中的最小者
    for(j=0;j<g.n;++j)
    {
      if(vset[j]==0&&lowcost[j]<min)
      {
        min=lowcost[j];
        k=j;
      }
    vset[k]=1;
    v=k;
    sum+=sum;
    // 下面这个循环以刚并入的顶点v为媒介更新候选边
    for(j=0;j<g.n;++j)
      if(vset[j]==0&&g.edges[v][j]<lowcost[j])
        lowcost[j]=g.edges[v][j];
  }
}

4. 最短路径

4.1 迪杰斯特拉算法 Dijkstra

迪杰斯特拉算法 Dijkstra

4.2 佛罗伊德算法 Floyd

佛罗伊德算法 Floyd

void Floyd(MGraph g, int Path[][maxSize])
{
    int i,j,k;
    int A[maxSize][maxSize];
    /* 这个双循环对数组A[][]和Path[][]进行了初始化*/
    for(i=0;i<g.n;++i)
        for (j=0;j<g.n;++j)
        {
            A[i][j]=g.edges[i][j];
            Path[i][j]=-1;
        }
    /* 下面的三层循环是主要操作,完成了以k为中间点对所有的顶点对{i,j}进行检测和修改*/
    for(k=0;k<g.n;++k)
        for(i=0;i<g.n;++i)
            for(j=0;j<j.n;++j)
                if(A[i][j]>A[i][k]+A[k][i])
                {
                    A[i][j]=A[i][k]+A[k][i];
                    Path[i][j]=k;
                }
}

5. 拓扑结构

拓扑结构

// 以邻接表为存储结构
typedef struct
{
    char data;
    int count;
    ArcNode *firstarc; // 统计顶点当前的入度
} VNode;

int TopSort(AGraph *G) //注意这里传入的是图的地址指针
{
    int i,j,n=0;
    int stack[maxSize], top=-1; //用于记录当前图中入度为0的顶点
    ArcNode *p;
    /* 将图中入度为0的顶点入栈 */
    for(i=0;i<G->n;++j) //图中顶点从0开始编号
        if(G->adjlist[i].count==0) //假设count已经存储了所有入度为0的顶点
            stack[++top]=i;
    /* 关键操作 */
    while(top!=-1)
    {
        i=stack[top--];
        ++n;
        count<<i<<" ";
        p=G->adjlist[i].firstarc;
        /* 此循环实现了将所有由此顶点引出的边所指向的顶点的入度都减少1 */
        /* 并将这个过程中入度为0的顶点入栈 */
        while(p!=NULL)
        {
            j=p->adjvex;
            --(G->adjlist[j].count);
            if(G->adjlist[j].count==0)
                stack[++top]=j;
            p=p->nextarc;
        }
    }
    /* 关键操作结束 */
    if(n==G->n)
        return 1;
    else
        return 0;
}

6. 关键路径

一般不考代码实现

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值