创建的有向图为:{6条边,8个顶点}<1,2><1,3><1,4><3,2><3,4><4,5><6,4><6,5>
#include<stdio.h>
/*==============================十字链表的存储结构===========================*/
#define MAX_VERTEX_NUM 20
#define QUEUE_MAXSIZE 100
#define MAXSTACK 100
int top=-1;
int visited[MAX_VERTEX_NUM];
int indegree[MAX_VERTEX_NUM];
typedef int VRType;
typedef int VertexType;
struct ArcBox {
int tailvex,headvex;
struct ArcBox *hlink,*tlink;
VRType weight;
};
struct VexNode {
VertexType data;
struct ArcBox *firstin,*firstout;
};
typedef struct {
struct VexNode xlist[MAX_VERTEX_NUM];
int vexnum,arcnum;
}OLGraph;
struct stack {
int ivex;
}stack[MAXSTACK],mythis;
#define pop stack[top--]
#define push(s) stack[++top] = (s)
/*============================================================================*/
/* */
/* 顺 序 队 列 */
/* */
/*============================================================================*/
typedef struct{
int data;
}elemtype;
typedef struct{
elemtype elem[QUEUE_MAXSIZE];
int front ,rear;
int length;
}QUEUE;
void queue_init(QUEUE *q)
{
(*q).front=(*q).rear=-1; (*q).length=0;
}
int queue_empty(QUEUE *q)
{
if((*q).length==0) return 1;
else return 0;
}
void queue_push(QUEUE *q,elemtype e)
{
if((*q).length==QUEUE_MAXSIZE) { printf("QUEUE IS FULL"); return ;}
(*q).rear=++(*q).rear%QUEUE_MAXSIZE;
(*q).elem[(*q).rear]=e;
(*q).length++;
if((*q).length==1&&(*q).front==-1) (*q).front=0;
}
void queue_pop(QUEUE *q,elemtype *e)
{
if((*q).length==0) { printf("QUEUE IS EMPTY"); return ;}
*e=(*q).elem[(*q).front++];
(*q).front=(*q).front%QUEUE_MAXSIZE;
(*q).length--;
if((*q).length==0) (*q).front=(*q).rear=-1;
}
/*============================十字链表的基本操作=============================*/
int LocateVex(OLGraph *G,VertexType v) /*确定顶点V的存储位置*/
{
int i;
for(i = 0;i < G->vexnum;i ++)
if(v == (G->xlist[i]).data )
return i;
}
/*返回ivex第一个邻接顶点的位置*/
int FirstAdjVex(OLGraph *G,int ivex,int mark)
{
int f_out,f_in; /*mark==1 则返回顶点出度的第一个邻接点;否则,返回入度的第一个邻接点*/
struct ArcBox *out,*in;
if(1 == mark)
{
out = G->xlist[ivex].firstout;
if(out != NULL) f_out = ((ivex == out->tailvex)?(out->headvex):(out->tailvex));
else f_out = -1;
return f_out;
}
else
{
in = G->xlist[ivex].firstin;
if(in != NULL) f_in = (ivex == in->tailvex)?(in->headvex):(in->tailvex);
else f_in = -1;
return f_in ;
}
}
/*返回ivex相对于wvex的下一个邻接顶点的位置*/
int NextAdjVex(OLGraph *G,int ivex ,int wvex,int mark)
{
int f_out,f_in,temp; /*mark==1 则返回顶点出度的下一个邻接点;否则,返回入度的下一个邻接点*/
struct ArcBox *out,*in;
if(1 == mark)
{ /*返回顶点ivex的出度相对于wvex的下一个邻接点*/
out = G->xlist[ivex].firstout;
if(out != NULL)
{
while(out != NULL )
{
temp=( (ivex == out->tailvex) ? (out->headvex) : (out->tailvex) );
if(wvex == temp)
{
out = out->tlink;
if(out != NULL) f_out = (ivex == out->tailvex)?(out->headvex):(out->tailvex);
else f_out = -1;
return f_out;
}
out = out->tlink;
}/*while*/
}
else { f_out= -1; return f_out;}
}
else
{ /*返回顶点ivex的入度相对于wvex的下一个邻接点*/
in = G->xlist[ivex].firstin;
if(in != NULL)
{
while(in != NULL )
{
temp=( (ivex == in->tailvex) ? (in->headvex) : (in->tailvex) );
if(wvex == temp)
{
in = in->hlink;
if(in != NULL) f_in = (ivex == in->tailvex)?(in->headvex):(in->tailvex);
else f_in = -1;
return f_in;
}
in = in->hlink;
}/*while*/
}
else{ f_in = -1; return f_in; }
}
}
/*--------------------------11、深度优先遍历---------------------------------*/
/* int visited[MAX_VERTEX_NUM] */
void VisitFunc(OLGraph *G,int ivex)
{
printf("%6d",G->xlist[ivex].data);
}
void DFS( OLGraph *G,int i_vex )
{
int w_vex;
int mark=1; /* 求有向图的强连通分量时用,逆向遍历,mark=1为出度标志,mark=0否则为入度标志*/
visited[i_vex] = 1; VisitFunc(G,i_vex);
for(w_vex = FirstAdjVex(G,i_vex,mark); w_vex>=0; w_vex=NextAdjVex(G,i_vex,w_vex,mark) )
if(!visited[w_vex]) DFS(G,w_vex);
}
void DFSTraverse( OLGraph *G )
{
int i_vex;
for(i_vex = 0; i_vex < G->vexnum; i_vex ++) visited[i_vex] = 0;
for(i_vex = 0; i_vex < G->vexnum; i_vex ++)
if(!visited[i_vex]) DFS(G,i_vex);
}
/*-------------------------- 12、广度优先遍历----------------------------------*/
void BFSTraverse(OLGraph *G)
{
int i_vex,u_vex,w_vex,mark=1;
elemtype e1,e2,e3;
QUEUE Q;
for(i_vex = 0; i_vex < G->vexnum;i_vex ++) visited[i_vex] = 0;
queue_init(&Q);
for(i_vex = 0;i_vex < G->vexnum;i_vex ++)
if(!visited[i_vex])
{
visited[i_vex]=1; VisitFunc(G,i_vex);
e1.data = i_vex;
queue_push(&Q,e1);
while(!queue_empty(&Q))
{
queue_pop(&Q,&e2); u_vex = e2.data;
for(w_vex = FirstAdjVex(G,u_vex,mark);w_vex >= 0;w_vex = NextAdjVex(G,u_vex,w_vex,mark))
if(!visited[w_vex])
{
visited[w_vex]=1;VisitFunc(G,w_vex);
e3.data =w_vex;queue_push(&Q,e3);
}/* if */
}/* while */
}/* if */
}
/*===============================拓扑排序AOV=================================*/
void FindDegree(OLGraph *G)
{
int ivex,in_count;
struct ArcBox *in;
for(ivex = 0;ivex < G->vexnum;ivex ++)
{
in_count=0;
in = G->xlist[ivex].firstin;
while(in != NULL ){ in_count++; in = in->hlink;}/*while*/
indegree[ivex] = in_count;
}
}
int TopologicalSort(OLGraph *G)
{
int i,count,v,w,mark=1;
struct stack intemp;
FindDegree(G);
top=-1;
for(i=0;i<G->vexnum;i++)
if(!indegree[i]) { mythis.ivex = i; push(mythis); }
count = 0;
while(-1 != top)
{
mythis = pop; printf("%6d",G->xlist[mythis.ivex].data); ++count;
for(w = FirstAdjVex(G,mythis.ivex,mark);w>= 0;w = NextAdjVex(G,mythis.ivex,w,mark))
if(!(--indegree[w])){ intemp.ivex = w; push(intemp); }
}
if(count < G->vexnum) return 0;
else return 1;
}
/*==========================================================================*/
int CreateDN(OLGraph *G) /*创建十字链表*/
{
int i,j,k;
VRType weight=0;
VertexType v1,v2;
struct ArcBox *p;
printf("/n Orthogonal List Create DG/n");
printf("/n/n The Graph's number of Vertex :"); scanf("%d",&(G->vexnum));
printf(" The Graph's number of Arcnum :"); scanf("%d",&(G->arcnum));
printf("/n");
for(i=0;i<G->vexnum;i++) {
printf(" The Graph's %d Vertex's NAME:",i+1); scanf("%d",&(G->xlist[i].data));
G->xlist[i].firstin = NULL;
G->xlist[i].firstout = NULL;
}
for(k=0;k<G->arcnum;k++)
{
printf("/n The %d Arc ./n",k+1);
printf(" The tail vertex:");do{ scanf("%d",&v1);if((v1<=0)||(v1>G->vexnum))printf(" ERROR/n The tail vertex:"); }while((v1<=0)||(v1>G->vexnum));
printf(" The head vertex:");do{ scanf("%d",&v2);if((v2<=0)||(v2>G->vexnum))printf(" ERROR/n The head vertex:"); }while((v2<=0)||(v2>G->vexnum));
/*printf(" The arc weight:");do{ scanf("%d",&weight); if(weight < 0) printf(" ERROR/n The arc weight:"); }while(weight < 0);*/
i = LocateVex(G,v1); j = LocateVex(G,v2);
p = (struct ArcBox *)malloc(sizeof(struct ArcBox));
p->tailvex = i;
p->headvex = j;
p->hlink = G->xlist[j].firstin;
p->tlink = G->xlist[i].firstout;
p->weight = weight;
G->xlist[j].firstin = G->xlist[i].firstout = p;
}
return 0;
}
void Prin_OLGraph(OLGraph *G) /*输出十字链表*/
{
int k;
struct ArcBox *p;
printf("/n/n The Vertex Outdegree =>/n/n");
for(k = 0;k <G->vexnum;k ++)
{
p = G->xlist[k].firstout;
printf(" /tVertex %d :",k+1);
while( p != NULL ){ printf(" (%d,%d) ",1+p->tailvex,1+p->headvex); p = p->tlink; }
printf("/n");
}
printf("/n/n The Vertex Indegree =>/n/n");
for(k = 0;k <G->vexnum;k ++)
{
p = G->xlist[k].firstin;
printf(" /tVertex %d :",k+1);
while( p != NULL ){ printf(" (%d,%d) ",1+p->tailvex,1+p->headvex); p = p->hlink; }
printf("/n");
}
}
/*============================================================================*/
int main()
{
int out,next_out;
OLGraph G;
CreateDN(&G);
Prin_OLGraph(&G);
printf("/n DFSTraverse AMGraph:/n");
DFSTraverse(&G);
printf("/n BFSTraverse AMGraph:/n");
BFSTraverse(&G);
printf("/n TopologicalSort AMGraph:/n");
TopologicalSort(&G);
getch();
}