前几天就讲了,考电路的前一天晚上写了一下,但是因为54的活动,今天才有空写下来。题目如下:
看一下题,就是用邻接表存一个图,然后用dj算法来求出0节点到其他节点的最短路径,最后的输出格式要求从短到长,最后输出不可到达,所以最后要排一下序。
首先创建3 3 1 2 1 1 3 4 2 3 2的邻接表如下图:
dj算法其实是贪心,通过寻找当前节点到四周节点的最小步数节点,以其更新四周的路径长度,不断循环,直到无路可走。过程如下:
最后的输出使用了一个快速排序,之后先输出大于0的,在输出-1即可。
以下是我的实现:
#include <stdio.h> #include <stdlib.h> struct edgeNode { int headVex; int weight; struct edgeNode *next; }; struct vexNode { int vex; struct edgeNode *head; }; struct graphList { struct vexNode vex[3000]; int vexNum; int edgeNum; }; struct step { int flags[3000]; int stepN[3000]; }; void run (); void createNewGraphList (struct graphList *gList); void clearVexNodes (struct graphList *gList); void createNewEdgeNode (int n,struct graphList *gList); void DJ(struct step *S,struct graphList *gList); void clearStep(struct step *S,struct graphList *gList); void initializeStep(struct step *S,struct graphList *gList); int judgeStep(struct step *S,struct graphList *gList); int findMinStepN(struct step *S,struct graphList *gList); void updateStepN(struct step *S,struct graphList *gList,int min); void print(struct step *S,struct graphList *gList); void swap(int *a,int *b); void quicksort(int array1[],int array2[],int maxlen,int begin,int end); int main() { run (); return 0; } void run () { struct graphList gList; struct step S; createNewGraphList (&gList); DJ (&S,&gList); print (&S,&gList); } void createNewGraphList (struct graphList *gList) { scanf ("%d%d",&(gList->vexNum),&(gList->edgeNum)); clearVexNodes (gList); int i,vex; for (i=0;i<gList->edgeNum;i++) { scanf ("%d",&vex); gList->vex[vex-1].vex=vex; createNewEdgeNode (vex-1,gList); } } void clearVexNodes (struct graphList *gList) { int i; for (i=0;i<gList->vexNum;i++) { gList->vex[i].vex=0; gList->vex[i].head=NULL; } } void createNewEdgeNode (int n,struct graphList *gList) { struct edgeNode *p,*q; int headVex; p=(struct edgeNode *)malloc(sizeof(struct edgeNode)); scanf ("%d",&headVex); p->headVex=headVex-1; scanf ("%d",&(p->weight)); p->next=NULL; if (gList->vex[n].head==NULL) { gList->vex[n].head=p; } else { q=gList->vex[n].head; while (q->next) { q=q->next; } q->next=p; } } void DJ(struct step *S,struct graphList *gList) { int min; clearStep (S,gList); initializeStep (S,gList); while (judgeStep (S,gList)) { min=findMinStepN (S,gList); updateStepN (S,gList,min); } } void clearStep(struct step *S,struct graphList *gList) { int i; for (i=0;i<gList->vexNum;i++) { S->flags[i]=-1; S->stepN[i]=0; } } void initializeStep(struct step *S,struct graphList *gList) { struct edgeNode *p; p=gList->vex[0].head; while (p) { S->flags[p->headVex]=1; S->stepN[p->headVex]=p->weight; p=p->next; } } int judgeStep(struct step *S,struct graphList *gList) { int i; for (i=1;i<gList->vexNum;i++) { if (S->flags[i]==1) { return 1; } } return 0; } int findMinStepN(struct step *S,struct graphList *gList) { int i,min=99999,n=-1; for (i=1;i<gList->vexNum;i++) { if (S->flags[i]==1) { if (S->stepN[i]<min) { min=S->stepN[i]; n=i; } } } return n; } void updateStepN(struct step *S,struct graphList *gList,int min) { struct edgeNode *p; int minStepN=S->stepN[min]; p=gList->vex[min].head; S->flags[min]=0; while (p) { if (S->flags[p->headVex]==1) { if (p->weight+minStepN<S->stepN[p->headVex]) { S->stepN[p->headVex]=p->weight+minStepN; } } else { if (S->flags[p->headVex]==-1) { S->flags[p->headVex]=1; S->stepN[p->headVex]=p->weight+minStepN; } } p=p->next; } } void print(struct step *S,struct graphList *gList) { int i; int nList[3000]={0}; int noList[3000]={0}; for (i=1;i<gList->vexNum;i++) { if (S->flags[i]==-1) { nList[i]=-1; } else { nList[i]=S->stepN[gList->vex[i].vex-1]; } noList[i]=i+1; } quicksort (nList,noList,gList->vexNum,1,gList->vexNum-1); for (i=1;i<gList->vexNum;i++) { if (nList[i]>0) { printf ("1 %d %d\n",noList[i],nList[i]); } } for (i=1;i<gList->vexNum;i++) { if (nList[i]==-1) { printf ("1 %d %d\n",noList[i],nList[i]); } } } void swap(int *a,int *b) { int temp; temp=*a; *a=*b; *b=temp; } void quicksort(int array1[],int array2[],int maxlen,int begin,int end) { int i,j; if(begin<end) { i=begin + 1; j=end; while(i<j) { if(array1[i]>array1[begin]) { swap(&array1[i],&array1[j]); swap(&array2[i],&array2[j]); j--; } else { i++; } } if(array1[i]>=array1[begin]) { i--; } swap(&array1[begin],&array1[i]); swap(&array2[begin],&array2[i]); quicksort(array1,array2,maxlen,begin,i); quicksort(array1,array2,maxlen,j,end); } }
以下是各函数的注释:
void run () { struct graphList gList; struct step S; createNewGraphList (&gList);//创建图 DJ (&S,&gList);//dj算法 print (&S,&gList);//输出结果 }
void createNewGraphList (struct graphList *gList) { scanf ("%d%d",&(gList->vexNum),&(gList->edgeNum));//输入顶点数边数 clearVexNodes (gList);//清空 int i,vex; for (i=0;i<gList->edgeNum;i++) { scanf ("%d",&vex); gList->vex[vex-1].vex=vex;//循环输入顶点 createNewEdgeNode (vex-1,gList);//创建边表节点 } }
void clearVexNodes (struct graphList *gList) { int i; for (i=0;i<gList->vexNum;i++)//循环清空 { gList->vex[i].vex=0; gList->vex[i].head=NULL; } }
void createNewEdgeNode (int n,struct graphList *gList) { struct edgeNode *p,*q; int headVex; p=(struct edgeNode *)malloc(sizeof(struct edgeNode));//创建节点 scanf ("%d",&headVex);//输入指向的节点 p->headVex=headVex-1;//录入指向节点的序号 scanf ("%d",&(p->weight));//输入权值 p->next=NULL; if (gList->vex[n].head==NULL) { gList->vex[n].head=p;//若表空,就是头结点 } else//否则连接到最后 { q=gList->vex[n].head; while (q->next) { q=q->next; } q->next=p; } }
void DJ(struct step *S,struct graphList *gList) { int min; clearStep (S,gList);//清空步数 initializeStep (S,gList);//初始化步数 while (judgeStep (S,gList))//当有路走就循环 { min=findMinStepN (S,gList);//的到最小步数节点的序号 updateStepN (S,gList,min);//以其更新步数 } }
void clearStep(struct step *S,struct graphList *gList) { int i; for (i=0;i<gList->vexNum;i++) { S->flags[i]=-1;//-1表无路,0表以找到最短路径,1表未找到最短路径 S->stepN[i]=0;//到此节点的步数为0 } }
void initializeStep(struct step *S,struct graphList *gList) { struct edgeNode *p; p=gList->vex[0].head; while (p)//循环边表 { S->flags[p->headVex]=1;//设置为未找到最短路径 S->stepN[p->headVex]=p->weight;//设置到此节点步数 p=p->next; } }
int judgeStep(struct step *S,struct graphList *gList) { int i; for (i=1;i<gList->vexNum;i++)//循环所有节点 { if (S->flags[i]==1)//若有节点被设为未找到最短路径 { return 1;//返回1,继续循环 } } return 0;//返回0,结束循环 }
int findMinStepN(struct step *S,struct graphList *gList) { int i,min=99999,n=-1; for (i=1;i<gList->vexNum;i++)//循环所有节点 { if (S->flags[i]==1)//若被设为未找到最短路径 { if (S->stepN[i]<min)//若比已知最小小,就替换 { min=S->stepN[i]; n=i; } } } return n;//返回得到的最小步数的节点的编号 }
void updateStepN(struct step *S,struct graphList *gList,int min) { struct edgeNode *p; int minStepN=S->stepN[min]; p=gList->vex[min].head; S->flags[min]=0; while (p)//循环边表 { if (S->flags[p->headVex]==1)//若未找到最短路径 { if (p->weight+minStepN<S->stepN[p->headVex])//若新的走法的步数较少 { S->stepN[p->headVex]=p->weight+minStepN;//就更新到此节点的步数 } } else { if (S->flags[p->headVex]==-1)//若此节点无路到达 { S->flags[p->headVex]=1; S->stepN[p->headVex]=p->weight+minStepN;//新的走法有路到达,更新其步数 } } p=p->next; } }
void print(struct step *S,struct graphList *gList) { int i; int nList[3000]={0};//步数 int noList[3000]={0};//节点编号 for (i=1;i<gList->vexNum;i++) { if (S->flags[i]==-1)//若无路到达,步数就是-1 { nList[i]=-1; } else { nList[i]=S->stepN[gList->vex[i].vex-1];//否则就是步数 } noList[i]=i+1;//节点编号赋值 } quicksort (nList,noList,gList->vexNum,1,gList->vexNum-1);将步数从小到大排,编号随之改变 for (i=1;i<gList->vexNum;i++) { if (nList[i]>0)//先输出有路到达的 { printf ("1 %d %d\n",noList[i],nList[i]); } } for (i=1;i<gList->vexNum;i++) { if (nList[i]==-1)//再输出无路到达的 { printf ("1 %d %d\n",noList[i],nList[i]); } } }
void swap(int *a,int *b)//交换数值 { int temp; temp=*a; *a=*b; *b=temp; }
void quicksort(int array1[],int array2[],int maxlen,int begin,int end)//以array1排序,同时改变array2 { int i,j; if(begin<end) { i=begin + 1; j=end; while(i<j) { if(array1[i]>array1[begin]) { swap(&array1[i],&array1[j]); swap(&array2[i],&array2[j]); j--; } else { i++; } } if(array1[i]>=array1[begin]) { i--; } swap(&array1[begin],&array1[i]); swap(&array2[begin],&array2[i]); quicksort(array1,array2,maxlen,begin,i); quicksort(array1,array2,maxlen,j,end); } }以上就是我的实现。