数据结构-实验八(图)

1.编写程序输出以邻接表为存储结构的无向图的各顶点的度。

/*
编写程序输出以邻接表为存储结构的无向图的各顶点的度。
*/
/**********************************/
/*文件名称:lab8_01.c                 */
/**********************************/
#include "ljb.h"
/* 输出以邻接表为存储结构的无向图g的各顶点的度 */
void degree(LinkedGraph g)
{
	int i,count=0;
	EdgeNode *p;
	for(i=0;i<g.n;i++)
	{
		p=g.adjlist[i].FirstEdge;
		printf("%c为头节点的度数为: ",g.adjlist[i].vertex);
		while(p)
		{
			count++;
			p=p->next;
		}
		printf("%d\n",count);
		count=0;
	}
}
int main()
{ LinkedGraph g;
  creat(&g,"g11.txt",0);  	/*已知g11.txt中存储了图的信息*/
  printf("\n The graph is:\n");
  print(g);
  degree(g);
  return 0;
}

2.编写程序实现图采用邻接表存储结构,编程对图进行广度优先遍历。

/*
图采用邻接表存储结构,编程对图进行广度优先遍历。
*/
/**********************************/
/*文件名称:lab8_02.c                 */
/**********************************/
#include "ljb.h"
int visited[M];  				/*全局标志向量*/
/*请将本函数补充完整,并进行测试*/
void bfs(LinkedGraph g, int i)
{ /*从顶点i出发广度优先变量图g的连通分量*/
	EdgeNode *p;
	int j;
	int quene[M],front,rear;
	front=rear=0;
	printf("%c",g.adjlist[i].vertex);
	visited[i]=1;
	quene[rear++]=i;
	while(rear>front)
	{
		j=quene[front++];
		p=g.adjlist[i].FirstEdge;
		while(p)
		{
			if(visited[p->adjvex]==0)
			{
				printf("%c",g.adjlist[p->adjvex].vertex);
				quene[rear++]=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;
}

 3.编写程序实现图采用邻接表存储结构,编程对图进行深度优先遍历。

/*
    图采用邻接表存储结构,编程对图进行深度优先遍历。
*/
#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])
		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*/
}

4.编写程序实现Prim求解最小生成树算法

/*********************************************/
/*           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];
		}
		for(k=0;k<g.n-3;k++)
		{
			min=tree[k].length;
			s=k;
			for(j=k+1;j<g.n-1;j++)
			{
				if(tree[j].length<min)
				{
					min=tree[j].length;
					s=j;
				}
			}
			v=tree[s].en;
			x=tree[s];
			tree[s]=tree[k];
			tree[k]=x;
			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;
				}
			}
		} /*依次求当前(第k条)最小两栖边,并加入TE*/
  /*由于新顶点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);  /*创建无向图的邻接矩阵*/
   prim(g,tree);        /*求解图的最小生成树*/
   return 0;
 }

5.编写程序实现Dijkstra单源最短路径算法

/***************************************************/
/*          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;
	/* 第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];
		}
		printf("\n%c---\n",g.vexs[v],min);
		if(min==FINITY)
		return ;
		final[v]=TRUE;
		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;
			}
		}
	} 
 /*第3步 修改S与V-S中各结点的距离*/
 }
/*函数功能:输出有向图的最短路径
函数参数:邻接矩阵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;
  }

6.编写程序实现拓扑排序算法

/***************************************/
/*             拓扑排序算法            */
/***************************************/
#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;     // 标记为已访问
       }
   }
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--; // 相邻顶点的入度减1
           if (g.adjlist[j].id == 0 && !flag[j]) {
               queue[t++] = j;  // 如果入度变为0,则进队
               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;
}

ljjz.h代码

/********************************************/
/*         邻接矩阵类型定义的头文件		 	*/
/*               文件名:ljjz.h	   			*/
/********************************************/

#include <stdio.h>
#define FINITY 5000   			/*此处用5000代表无穷大*/
#define M 20          				/*最大顶点数*/
typedef char vertextype;  		/*顶点值类型*/
typedef int edgetype;     		/*权值类型*/
typedef struct{
	vertextype vexs[M];    		/*顶点信息域*/
	edgetype edges[M][M]; 	/*邻接矩阵*/
	int n,e;  							/*图中顶点总数与边数*/
} Mgraph;   							/*邻接矩阵表示的图类型*/
/*   函数功能:建立图的邻接矩阵存储结构
     函数参数:邻接矩阵的指针变量g;存放图信息的文件名s;图的类型c,c=0表示建立无向图,否则表示建立有向图 
   函数返回值:无
*/ 
void creat(Mgraph *g,char *s ,int c)
{int i,j,k,w;           /*建立网络的邻接矩阵存储结构*/
   FILE *rf ;
   rf = fopen(s, "r") ;   /*从文件中读取图的边信息*/
   if (rf)
   {
   fscanf(rf,"%d%d",&g->n,&g->e);  /*读入图的顶点数与边数*/
   for(i=0;i<g->n;i++)    /*读入图中的顶点值*/
      fscanf(rf,"%1s",&g->vexs[i]);
 
   for(i=0;i<g->n;i++)    /*初始化邻接矩阵*/
      for(j=0;j<g->n;j++)
       if (i==j) g->edges[i][j]=0;
       else g->edges[i][j]=FINITY;

   for (k=0;k<g->e;k++)  /*读入网络中的边*/
    {fscanf(rf,"%d%d%d", &i,&j,&w);
     g->edges[i][j]=w;
     if (c==0) g->edges[j][i]=w;   /*如果C==0则建立无向图邻接矩阵,否则建立有向图邻矩阵*/
    }
   fclose(rf);
   }
   else g->n=0;
}


void  print(Mgraph g)
{/*辅助函数,输出邻接矩阵表示的图g*/
  int i,j;
 
  for (i=0;i<g.n;i++)
   { printf("%c ",g.vexs[i]); 
    }
    printf("\n");
  for (i=0;i<g.n;i++)
    {    for (j=0;j<g.n;j++)
         {printf("%6d",g.edges[i][j]);
        }
          printf("\n");
       }
  }

ljb.h代码

/*********************************************/
/*    邻接表存储结构   文件名:ljb.h     	 */
/*********************************************/

#include <stdio.h>
#include <stdlib.h>
#define M 20					/*预定义图的最大顶点数*/
typedef char DataType;  /*顶点信息数据类型*/
typedef struct node{    /*边表结点*/
   int adjvex;                  /*邻接点*/
   struct node *next;
}EdgeNode;

typedef struct vnode{   /*头结点类型*/
   DataType vertex;         /*顶点信息*/
   EdgeNode *FirstEdge; /*邻接链表头指针*/
}VertexNode;

typedef struct{           /*邻接表类型*/
 VertexNode adjlist[M];  /*存放头结点的顺序表*/
 int n,e;                 /*图的顶点数与边数*/
}LinkedGraph;


/*函数功能:建立图的邻接表
  函数参数:邻接表指针变量g;存放图信息的文件名filename;图的类型参数c,c=0表示建立无向图,否则表示建立有向图 
  函数返回值:无
*/ 
void creat(LinkedGraph *g,char *filename,int c)
    { 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;         /*边表置为空表*/
       }
  
      for(k=0;k<g->e;k++)                     /*循环e次建立边表*/
        {
            fscanf(fp,"%d%d",&i,&j);                 /*输入无序对(i,j)*/
            s=(EdgeNode *)malloc(sizeof(EdgeNode));
            s->adjvex=j;                         /*邻接点序号为j*/
            s->next=g->adjlist[i].FirstEdge;
            g->adjlist[i].FirstEdge=s;           /*将新结点*s插入顶点vi的边表头部*/
            if (c==0)                            /*无向图*/ 
            {
            s=(EdgeNode *)malloc(sizeof(EdgeNode));
            s->adjvex=i;                         /*邻接点序号为i*/
            s->next=g->adjlist[j].FirstEdge;
            g->adjlist[j].FirstEdge=s;           /*将新结点*s插入顶点vj的边表头部*/
			}
        }
    fclose(fp);
    }
    else
    g->n=0;
   }
/*---函数print():输出邻接表存储结构---*/
void print(LinkedGraph  g)
{  EdgeNode *p;
   int i;
   for (i=0;i<g.n;i++)
    {   printf("%c",g.adjlist[i].vertex);
        p=g.adjlist[i].FirstEdge;
        while (p)
        {   printf("-->%d",p->adjvex);
            p=p->next;
        }
     printf("\n");
   }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值