我好不容易心动一次-你却让我输的那么狼狈

Question one

/*
编写程序输出以邻接表为存储结构的无向图的各顶点的度。
*/
/**********************************/
/*文件名称:lab8_01.c                 */
/**********************************/
#include "ljb.h"
/* 输出以邻接表为存储结构的无向图g的各顶点的度 */
void degree(LinkedGraph g)
{
	EdgeNode *p;
	int count;//用来保存各个节点的度
	int i;
	for(i = 0; i < g.n; i ++)
	{
		count = 0;
		p = g.adjlist[i].FirstEdge;//将p放在村储存与该点相邻的点的单链表的头结点上
		while(p)
		{
			count++;
			p = p->next;//不断的遍历该链表,来获得其相连的所有的点
		}
		printf("D(%d) = %d\n",i, count);//输出该点的度即可
	}
}
int main()
{ LinkedGraph g;
  creat(&g,"g11.txt",0);  	/*已知g11.txt中存储了图的信息*/
  printf("\n The graph is:\n");
  print(g);
  degree(g);
  return 0;
}

Question two

/*
图采用邻接表存储结构,编程对图进行广度优先遍历。
*/
/**********************************/
/*文件名称:lab8_02.c                 */
/**********************************/
#include "ljb.h"
int visited[M];  				/*全局标志向量*/
/*请将本函数补充完整,并进行测试*/
void bfs(LinkedGraph g, int i)
{ /*从顶点i出发广度优先变量图g的连通分量*/
	int queue[M], v;
	int head = 0, end = 0;//BFS的可以通过数据结构来实现
	EdgeNode *p;
	queue[end++] = i;//将目前的第一个节点导入的队列
	visited[i] = 1;//表示这个的节点已经被看过了
	while(head < end)//设置结束条件
	{
		v = queue[head++];//目前导入当前的结果
		printf("%c ",g.adjlist[v].vertex);//输出当前的节点
		p = g.adjlist[v].FirstEdge;//p为的指向的周围的节点
		while(p)
		{
			if(visited[p->adjvex] == 0)//如果这个节点没有被探查,就把这个节点加入队列
			{
				queue[end++] = p->adjvex;
				visited[p->adjvex] = 1;
			}
		p = p->next;//遍历到结果的下一个的
		}
	}
	
}


/*函数功能:广度优先遍历图g
  函数参数:邻接表g
*/
int BfsTraverse(LinkedGraph g)
{  int i,count=0;
   for (i=0;i<g.n;i++)
       visited[i]=0;     /*初始化标志数组*/

   for (i=0;i<g.n;i++)
       if (!visited[i])  /*vi未访问过*/
       {printf("\n");
        count++;            /*连通分量个数加1*/
        bfs(g,i);
       }
   return count;
 }

int main()
{ 	  LinkedGraph g;
      int count;
      creat(&g,"g11.txt",0);  		/*创建图的邻接表*/
      printf("\n The graph is:\n");
      print(g);
      printf("广度优先遍历序列为:\n");
      count=BfsTraverse(g);     	/*从顶点0出发广度优先遍历图g*/
      printf("\n该图共有%d个连通分量。\n",count);
      return 0;
}


Question three

/*
    图采用邻接表存储结构,编程对图进行深度优先遍历。
*/

#include "ljb.h"
int visited[M];
/*请将本函数补充完整,并进行测试*/

void dfs(LinkedGraph g,int i)
{   /*从顶点i开始深度优先遍历图的连通分量*/
    EdgeNode *p;
  	printf("visit vertex: %c \n",g.adjlist[i].vertex);/*访问顶点i*/
  	visited[i]=1;
  	p=g.adjlist[i].FirstEdge;
  	while (p)                 /*从p的邻接点出发进行深度优先搜索*/
    {
		if(visited[p->adjvex] == 0)
			dfs(g, p->adjvex);
		p = p->next;
    }
}
/*函数功能:深度优先遍历图
  函数参数:图的邻接表g
*/
void DfsTraverse(LinkedGraph g)
{  int i;
   for (i=0;i<g.n;i++)
       visited[i]=0;     /*初始化标志数组*/
   for (i=0;i<g.n;i++)
       if (!visited[i])  /*vi未访问过*/
            dfs(g,i);
 }

int main()
{ LinkedGraph g;
  creat(&g,"g11.txt",0);  			/*创建图的邻接表*/
  printf("\n The graph is:\n");
  print(g);
  printf("深度优先遍历序列为:\n");
  DfsTraverse(g);    				/*从顶点0开始深度优先遍历图无向图g*/
}

Question four

/*********************************************/
/*           Prim求解最小生成树算法          */
/*********************************************/
#include "ljjz.h"

typedef struct edgedata  /*用于保存最小生成树的边类型定义*/
       { int beg,en;     /*beg,en是边顶点序号*/
         int length;     /*边长*/
       }edge;

/*函数功能:prim算法构造最小生成树
函数参数:图的邻接矩阵g;边向量edge
*/
void prim(Mgraph g, edge tree[M-1])
{  edge x;
   int d,min,j,k,s,v;

   /* 建立初始入选点,并初始化生成树边集tree*/
  for (v=1;v<=g.n-1;v++)//将所有边分成两类,一类是已经被加入的,另一种是还未被加入的
  {
      tree[v-1].beg=0;
      tree[v-1].en=v;
      tree[v-1].length=g.edges[0][v];
  }
  /*依次求当前(第k条)最小两栖边,并加入TE*/
  for (k=0;k<=g.n-3;k++)
  {
      min=tree[k].length;
      s=k;
      for (j=k+1;j<=g.n-2;j++)
            if (tree[j].length<min)//如果找到了的比当前的值还要小的就直接更新
            {
                    min=tree[j].length;
                    s=j;
            }
        v=tree[s].en;
        x=tree[s];
        tree[s]=tree[k];
        /*由于新顶点v的加入,修改两栖边的基本信息*/
        for (j=k+1;j<=g.n-2;j++)
        {
            d=g.edges[v][tree[j].en];
            if (d<tree[j].length)
            {
                tree[j].length=d;
                tree[j].beg=v;
            }
        }
  }
   /*输出最小生成树*/
    printf("\n最小生成树是:\n");/*输出最小生成树*/
    for (j=0;j<=g.n-2;j++)
        printf("\n%c---%c  %d\n",g.vexs[tree[j].beg],g.vexs[tree[j].en],tree[j].length);
    printf("\n最小生成树的根是: %c\n", g.vexs[0]);
 }

int  main()
  {
   Mgraph g;
   edge  tree[M-1];  /*用于存放最小生成树的M-1条边*/
   creat(&g,"g.txt",0);  /*创建无向图的邻接矩阵*/
   print(g);
   prim(g,tree);        /*求解图的最小生成树*/

   return 0;

  }



Question five

/***************************************************/
/*          Dijkstra单源最短路径算法               */
/***************************************************/
#include "ljjz.h"   /*引入邻接矩阵创建程序*/
typedef enum{FALSE,TRUE} boolean;/*false为0,true为1*/
typedef int dist[M];  /* 距离向量类型*/
typedef int path[M];  /* 路径类型*/

/*函数功能:Dijkstra算法求解单源最短路径
函数参数:图的邻接矩阵g;源点v0;路径向量p;距离向量d
*/
void dijkstra(Mgraph g,int v0,path p,dist d)
 { boolean final[M]; /*表示当前元素是否已求出最短路径*/
   int i,k,j,v,min,x;

   /*  第1步  初始化集合S与距离向量d */
    for (v=0;v<g.n;v++)//初始化与这个顶点有关的所有的边的距离
    {
        final[v]=FALSE;
        d[v]=g.edges[v0][v];
        if (d[v]<FINITY &&d[v]!=0)
                p[v]=v0; else p[v]=-1;//表示目前的边没有达到
    }
    final[v0]=TRUE;
    d[v0]=0;//将自己自身边权设置为0
   /* 第2步  依次找出n-1个结点加入S中   */
    for (i=1;i<g.n;i++)
    {
        min=FINITY;
        for (k=0;k<g.n;k++)
            if (!final[k] && d[k]<min)//如果找到了周围的边就更新了
            {
                v=k;
                min=d[k];
            }
            if (min==FINITY)     return ;
            final[v]=TRUE;
    /*第3步 修改S与V-S中各结点的距离*/
    for (k=0;k<g.n;++k)
            if (!final[k] && (min+g.edges[v][k]<d[k]))
            {
                d[k]=min+g.edges[v][k];
                p[k]=v;
            }
    }
}
/*函数功能:输出有向图的最短路径
函数参数:邻接矩阵g;路径向量p;距离向量d
*/
void print_gpd(Mgraph g,path p,dist d)
 {
   int st[M],i,pre,top=-1;
   for (i=0;i<g.n;i++)
    { printf("\nDistancd: %7d , path:" ,d[i]);
      st[++top]=i;
      pre=p[i];
      while (pre!=-1)   /*从第i个顶点开始向前搜索最短路径上的顶点*/
        { st[++top]=pre;
          pre=p[pre];
         }
      while (top>0)
     printf("%2d",st[top--]);
    }
 }
/*---------- 主程序 ------------*/
int main()
 { Mgraph g;   /* 有向图 */
   path p;     /* 路径向量 */
   dist d;     /* 最短路径向量 */
   int v0;
   creat(&g,"g21.txt",1); /*假设图8.21所示的有向网G21的输入文件为g21.txt */
   print(g);        /*输出图的邻接矩阵*/
   printf("\n");
   printf("请输入源点编号:");
   scanf("%d",&v0);       /*输入源点*/
   dijkstra(g,v0,p,d);   /*求v0到其他各点的最短距离*/
   /*输出V0到其它各点的路径信息及距离*/
   print_gpd(g,p,d);

    return 0;
  }


Question six

/***************************************/
/*             拓扑排序算法            */
/***************************************/
#include<stdlib.h>
#include<stdio.h>
#define M 20
typedef char vertextype;
typedef struct node{      /*边结点类型定义*/
      int adjvex;
      struct node *next;
  }edgenode;
typedef struct de         /*带顶点入度的头结点定义*/
  {
   edgenode* FirstEdge;
   vertextype vertex;
   int id;                /*顶点的入度域*/
  }vertexnode;

typedef struct{           /*AOV网络的邻接表结构*/
      vertexnode adjlist[M];
      int n,e;
      }AovGraph;

void  creat(AovGraph *g,char *filename)       /*建立AOV网络的存储结构*/
 { int i,j,k;
   edgenode  *s;
   FILE *fp;
   fp=fopen(filename,"r");
   if (fp)
   {
   fscanf(fp,"%d%d",&g->n,&g->e);  /*输入图中的顶点数与边数*/

   for(i=0;i<g->n;i++)                        /*输入顶点值*/
      {fscanf(fp,"%1s",&g->adjlist[i].vertex);
       g->adjlist[i].FirstEdge=NULL;
       g->adjlist[i].id=0;       /*入度初始化为0*/
      }
   for(k=0;k<g->e;k++)
        { fscanf(fp,"%d%d",&i,&j);
         s=(edgenode*)malloc(sizeof(edgenode));
         s->adjvex=j;
         g->adjlist[j].id++;    /*顶点j的入度加1*/
         s->next=g->adjlist[i].FirstEdge;
         g->adjlist[i].FirstEdge=s;
        }
   }
 }

void print(AovGraph g)
{  edgenode *p;
   int i;
  for (i=0;i<g.n;i++)
   { printf("%c %d   ", g.adjlist[i].vertex,g.adjlist[i].id);
     p=g.adjlist[i].FirstEdge;
     while (p)
      { printf("%d-->",p->adjvex);
        p=p->next;
      }
     printf("\n");
   }
}
/*函数功能:拓扑排序
函数参数:AOV网邻接表存储结构变量g
函数返回值:拓扑排序输出的顶点个数
*/
int TopSort(AovGraph g)
 {int k=0,i,j,v, flag[M];
   int queue[M];  /*队列*/
   int h=0,t=0;
   edgenode* p;
   for (i=0;i<g.n;i++)  flag[i]=0;  /*访问标记初始化*/
    /*先将所有入度为0的结点进队*/
    /*将程序补充完整*/

  for (i=0;i<g.n;i++)
        if (g.adjlist[i].id==0)//如果这个节点没有前驱节点,那么就将这个节点入对
        {
            queue[t++]=i;
            flag[i]=1;//并且将标记更新为1
        }
   while (h<t)//设置边界条件
   {
       v=queue[h++];//取出队列的头结点
       printf("%c ",g.adjlist[v].vertex);//输出该节点的值
       k++;//记录输出的顶点的个数
       p=g.adjlist[v].FirstEdge;
       while (p)
       {
           j=p->adjvex;
           g.adjlist[j].id--;//指的是j减少了一个前驱结点
           if (g.adjlist[j].id==0 && flag[j]==0)//如果这个节点没有被扫描过并且没有前驱
           {  queue[t++]=j;
               flag[j]=1;
           }
           p=p->next;
       }

   }
    return k;  //返回输出的顶点个数
 }
int main()
{ int k=0;
  AovGraph g;
  creat(&g,"aov.txt");    /*假设图8.25所示的AOV网输入文件为aov.txt*/
  printf("\n图8.27所示AOV网的邻接表是:\n");
  print(g);
  k=TopSort(g);
  if(k<g.n) printf("\n该图存在环!\n");
  return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜狗原来是我自己

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值