NOJ-Dijkstra算法-西工大数据结构

    前几天就讲了,考电路的前一天晚上写了一下,但是因为54的活动,今天才有空写下来。题目如下:

《NOJ-Dijkstra算法-西工大数据结构》

    看一下题,就是用邻接表存一个图,然后用dj算法来求出0节点到其他节点的最短路径,最后的输出格式要求从短到长,最后输出不可到达,所以最后要排一下序。

    首先创建3  3      1  2  1       1  3  4       2  3  2的邻接表如下图:

《NOJ-Dijkstra算法-西工大数据结构》

    dj算法其实是贪心,通过寻找当前节点到四周节点的最小步数节点,以其更新四周的路径长度,不断循环,直到无路可走过程如下:

《NOJ-Dijkstra算法-西工大数据结构》

    最后的输出使用了一个快速排序,之后先输出大于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);
    }
}

    以上就是我的实现。

    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/qq_30180107/article/details/80206892
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞