前几天就讲了,考电路的前一天晚上写了一下,但是因为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);
}
}
以上就是我的实现。