文章都是摘录的网络中比较好的代码,因为图的四种存储方式中有两种方式(邻接矩阵和连接表)普通书上都有以此建立图的代码,所以在此不在累赘列出
*******************************************************************************
建立无向图的邻接多重表
题目:编写一个算法由依次输入的顶点数目,边的数目,各顶点的信息和各条边的信息建立无向图的邻接多重表。
一. 需求分析
这里需要两个主要字函数,一个是建立图,另一个是打印图。
二. 概要设计
首先是建立两个结点,一个是边结点,另一个是顶点结点,分别为struct Edge,struct Node,然后建立图,Create_ML_Graph(int Vertex1,NextEdge New),紧接着是打印Print_ML_Graph(struct Node *Head)。
三. 详细设计
#include <stdlib.h>
#include <stdio.h>
#define VertexNum 6
struct Edge
{int Marked;
int Vertex1;
int Vertex2;
struct Edge *Edge1;
struct Edge *Edge2;
};
typedef struct Edge *NextEdge;
struct Node
{int Vertex;
struct Edge *Next;
};
typedef struct Node *Graph;
struct Node Head[VertexNum];
void Create_ML_Graph(int Vertex1,NextEdge New)
{NextEdge Pointer;
NextEdge Previous;
Previous=NULL;
Pointer=Head[Vertex1].Next;
while(Pointer!=NULL)
{Previous=Pointer;
if (Pointer->Vertex1==Vertex1)
Pointer=Pointer->Edge1;
else Pointer=Pointer->Edge2;
}
if(Previous==NULL)
Head[Vertex1].Next=New;
else if(Previous->Vertex1==Vertex1)
Previous->Edge1=New;
else Previous->Edge2=New;
}
void Print_ML_Graph(struct Node *Head)
{NextEdge Pointer;
Pointer=Head->Next;
while( Pointer!=NULL)
{printf("(%d,%d)",Pointer->Vertex1,Pointer->Vertex2);
if(Head->Vertex==Pointer->Vertex1)
Pointer=Pointer->Edge1;
else if(Head->Vertex==Pointer->Vertex2)
Pointer=Pointer->Edge2;
}
printf("/n");
}
void main()
{int Source;
int Destinition;
NextEdge New;
int i;
for(i=0;i<VertexNum;i++)
{Head[i].Vertex=i;
Head[i].Next=NULL;}
while(1)
{printf("Please input the Edge's source:");
scanf("%d",&Source);
if(Source==-1) break;
printf("Please input the Edge's Destinition:");
scanf("%d",&Destinition);
if(Source>=VertexNum||Destinition>=VertexNum)
printf("@Error@:out of range!!/n");
else
{ New=(NextEdge) malloc(sizeof(struct Edge));
if(New!=NULL)
{New->Vertex1=Source;
New->Vertex2=Destinition;
New->Edge1=NULL;
New->Edge2=NULL;
Create_ML_Graph(Source,New);}
}
}
printf("##Graph##/n");
for(i=0;i<VertexNum;i++)
{printf("Vertex[%d]:",i);
Print_ML_Graph(&Head[i]);
}
}
四. 调试分析
这个题在调试时,除了常规的变量的定义和指针等错误外,主要是指针的值传不过去,导致打印的时候输入的图打印不出来,检查的时候看各指针是不是传过去了(用单步执行)。
五. 用户使用说明
运行程序时,首先是让你选择这时你输入1回车,这时让你输入头结点数,你可以输入1或2等(但不能大于6,这里设的最大值是6),紧接着让你输入尾结点,你照样输入(不能大于6),这样反复输入几次也就是几条边后回车,就可以看结果。
六. 测试结果
依次输入1,2,1,3,2,4,回车
可以看到 <1,2><1,3><2,4>
*************************************************************
有向图的十字链表存储结构
/**
说明:有向图的十字链表存储结构,同时编写了以下函数
1:建立十字链表的函数
2:输出有向图包括顶点和弧
3:计算顶点的入度和出度
4:深度优先遍历有向图
*/
#include <stdio.h>
#include <malloc.h>
#define OK 1
#define MAX 100
typedef char ElemType ;
typedef struct arcNode{ //定义有向图的弧结点
int tailvex, headvex; //弧尾和弧头在图中的位置
struct arcNode *hlink,*tlink;
}ArcNode;
typedef struct vexNode{ //定义顶点结点
ElemType data;
ArcNode *firstin,*firstout;
}VexNode;
typedef struct olgraph{ //定义有向图的十字链表
VexNode xlist[MAX];
int vexnum,arcnum;
}OLGraph;
ArcNode *ptr[MAX]; //定义访问图的辅助向量
int visited[MAX]; //定义顶点访问标志
int locateVex(OLGraph *g, ElemType a)
{ int s;
for(s=0;s<g->vexnum;s++)
if(g->xlist[s].data==a) return s;
return -1; //未找到则返回-1
}
void create(OLGraph *G)
{ int i,j,k;
ElemType v1,v2,v,vv;
ArcNode *p;
printf("/n/n/n/n*********** begin of creating *******************");
printf("/ninput number of vnum,arcnum:");
scanf("%d,%d",&G->vexnum,&G->arcnum);
printf("/ninput data of vex:/n");
for(i=0;i<G->vexnum;i++)
{ scanf("%*c%c",&v); //输入图中顶点
G->xlist.data=v;
G->xlist.firstin=NULL; //初始化以顶点为弧头和弧尾的链表
G->xlist.firstout=NULL;
}
printf("/n/ninput data of edge(v1v2)/n");
for(k=0;k<G->arcnum;k++) //输入图中的弧
{ scanf("%*c%c%c",&v1,&v2);
i=locateVex(G,v1);
j=locateVex(G,v2);
p=(ArcNode *)malloc(sizeof(ArcNode));
p->tailvex=i;p->headvex=j;
p->hlink=G->xlist[j].firstin;
p->tlink=G->xlist.firstout;
G->xlist[j].firstin=G->xlist.firstout=p;
}
printf("*********** end of creating *******************");
//return G;
}
void printGraph(OLGraph *g)
{ ArcNode *p;
int i;
printf("/n/nthe edges are:");
for(i=0; i<g->vexnum; i++) //输出图中的弧
{ p=g->xlist.firstout; printf("/n %c:",g->xlist.data);
while(p!=NULL)
{ printf(" %c----->%c",g->xlist.data, g->xlist[p->headvex].data);
p=p->tlink;
}
}
}
int outNumNode(ArcNode *p) //计算弧尾相同链表的结点数
{ int n=0;
while (p!=NULL) { n++; p=p->tlink; }
return n;
}
int inNumNode(ArcNode *p) //计算弧头相同链表的结点数
{ int n=0;
while (p!=NULL) { n++; p=p->hlink; }
return n;
}
int outDegree(OLGraph *g, ElemType a)//计算某结点的出度
{ int i, outNumber=0;
outNumber=outNumNode(g->xlist[locateVex(g,a)].firstout);
return outNumber;
}
int inDegree(OLGraph *g, ElemType a)//计算某结点的入度
{ int i, inNumber=0;
inNumber=inNumNode(g->xlist[locateVex(g,a)].firstin);
return inNumber;
}
void printDegree(OLGraph *g) //输出结点的度数
{ int i;
printf("/n/nthe outDegree of vexs are:");
for(i=0; i<g->vexnum; i++)
{ printf("/n %c: %d",g->xlist.data, outDegree(g,g->xlist.data)); }
printf("/n/nthe inDegree of vexs are:");
for(i=0; i<g->vexnum; i++)
{ printf("/n %c: %d",g->xlist.data, inDegree(g,g->xlist.data)); }
}
void dfs(OLGraph *g, int indexV) //以某顶点出发深度优先遍历图
{ int w;
printf("%4c", g->xlist[indexV].data);
visited[indexV]=1; // 访问此结点,并设置标志
while (ptr[indexV]!=NULL)
{ w= ptr[indexV]->headvex; //取结点的邻接顶点w
if( visited[w]==0 ) dfs(g, w);
ptr[indexV]=ptr[indexV]->tlink; // 记住顶点v 的邻接顶点位置,
} // 该邻接点在w之后
}
void depthFirst(OLGraph *g) //深度优先遍历图
{ int i;
for (i=0; i<g->vexnum; i++)
{ ptr=g->xlist.firstout; //每个顶点链表的第一个结点的地址
visited=0; //给每个结点一个未访问标记
}
printf("/n/nthe traverse of depthFirst are:");
for(i=0; i<g->vexnum; i++) //调用以顶点vi为出发点的深度优先遍历图G的算法
if (visited == 0) dfs(g,i);
printf("/nthe end of traverse");
}
void main()
{ OLGraph g;
create(&g);
printGraph(&g);
printDegree(&g);
depthFirst(&g);
}