您的位置:首页 > 理论基础 > 数据结构算法

图----数据结构图论总结(四)

2008-01-09 20:03 337 查看
文章都是摘录的网络中比较好的代码,因为图的四种存储方式中有两种方式(邻接矩阵和连接表)普通书上都有以此建立图的代码,所以在此不在累赘列出

*******************************************************************************

建立无向图的邻接多重表

题目:编写一个算法由依次输入的顶点数目,边的数目,各顶点的信息和各条边的信息建立无向图的邻接多重表。

一. 需求分析

这里需要两个主要字函数,一个是建立图,另一个是打印图。

二. 概要设计

首先是建立两个结点,一个是边结点,另一个是顶点结点,分别为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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: