图论算法之最短路径(有向无权图)

来源:互联网 发布:powell算法 编辑:程序博客网 时间:2024/05/20 08:22
1.算法介绍
下图是一个无权图G。使用某个顶点s作为输入参数,我们想要找出从s到所有其他顶点的最短路径。

设我们选择s为v2.此时立刻可以说出从s到v2的最短路径长为0的路径。把这个信息做个标记。如下图。

现在我们可以开始找寻所有与s距离为1的顶点。这些顶点通过考查与s邻接的那些顶点可以找到。此时我们看到,v0和v5与s出发只有一步之遥。标记如下。


现在可以找出那些从s出发最短路径恰为2的顶点。找到所有邻接到v0和v5的顶点。它们的最短路径还不知道。这次搜索告诉我们,到v1和v3的最短路径长为2。标记如下。

最后,通过考查那些与刚被赋值的v1和v3相邻的顶点我们可以发现。v4和v6各有一条三边最短路径。标记如下。

这种搜索一个图的方法称为广度优先搜索。该方法按层处理顶点。距开始点最近的那些顶点首先被赋值。而最远的那些顶点最后被赋值。
2 算法实现
对于每个顶点。我们将跟踪三个信息。首先,我们把从s开始到顶点的距离放在dist中。开始的时候,除s外所有顶点都是不可达到的。另外我们记录引起顶点变化的最后一个节点path。最后如果顶点被处理过,将使用known标记。
算法的实现需要使用队列和链表。我把它们放在附录中。
核心算法是unWeighted函数initGraph和initArr负责初始化图G。

////  main.c//  Unweighted2////  Created by Wuyixin on 2017/6/11.//  Copyright © 2017年 Coding365. All rights reserved.//#include <stdio.h>#include "LinkList.h"#include "Queue.h"typedef LinkedList Graph,Vertex;Graph initGraph(int n ,int g[n][n]);void initArr(int n ,int g[n][n]);/* 为了初始化方便,使用二维数组初始化图。实际上这是不允许的,因为使用链表就是为了避免使用二维数组*/Graph initGraph(int n ,int a[n][n]){    Graph g;    Vertex v,w;        g = malloc(n * sizeof(struct Node));    if (g == NULL)        exit(EXIT_FAILURE);        /* 初始化顶点 */    for (int i = 0; i < n; i++)  {        g[i].data = i;        g[i].next= NULL;        g[i].dist = INT_MAX;        g[i].known = 0;        g[i].path = 0;    }    for (int i = 0; i < n; i++) {        /* 构建顶点 */        v = &g[i];        for (int j = 0; j < n; j++) {            /* 构建邻接顶点 */            if (a[i][j] != UNAVAILABLE){                w = malloc(sizeof(struct Node));                if (w == NULL)                    exit(EXIT_FAILURE);                w->data = j;                w->next = NULL;                v->next = w;                                v = w;                            }        }            }        return g;}/* 初始化二维数组 */void initArr(int n ,int g[n][n]){    for (int i = 0; i < n; i++)        for (int j = 0; j < n; j++)            g[i][j] = UNAVAILABLE;    }void unWeighted(Graph g,int s,int n){    if (g == NULL)        exit(EXIT_FAILURE);    Queue q;    Vertex v,w,z;    int i;       q = createQueue(n);    makeEmpty(q);    g[s].dist = 0;    g[s].known = 1;        enQueue(s, q);        while (!isEmpty(q)) {        i = deQueue(q);        v = &g[i];        for (w = v->next; w != NULL; w = w->next) {            z = &g[w->data];            if (z->known == 0){                z->dist = v->dist + 1;                z->path = v->data;                z->known = 1;                enQueue(w->data, q);            }        }            }        disposeQueue(q);/* free queue */}void printDist(Graph g,int n){    for (int i = 0 ; i < n; i++)        printf("v%d--dist:%d  ",i,g[i].dist);    printf("\n");}int main(int argc, const char * argv[]) {    int a[7][7];    initArr(7, a);    a[0][1] = 1;    a[0][3] = 1;    a[1][3] = 1;    a[1][4] = 1;    a[2][0] = 1;    a[2][5] = 1;    a[3][2] = 1;    a[3][4] = 1;    a[3][5] = 1;    a[3][6] = 1;    a[3][4] = 1;    a[4][6] = 1;    a[6][5] = 1;        Graph g;    g = initGraph(7, a);        unWeighted(g , 2, 7);    printDist(g, 7);    return 0;}



3.附录:队列与链表
3.1 队列
(1)头文件
////  Queue.h//  Unweighted////  Created by Wuyixin on 2017/6/6.//  Copyright © 2017年 Coding365. All rights reserved.//#ifndef Queue_h#define Queue_h#include <stdio.h>#include <stdlib.h>#include <limits.h>typedef int ElemType;typedef struct QueueRecord *Queue;struct QueueRecord{    int capacity;    int front;    int rear;    int size;    ElemType *array;};/* 是否空 */int isEmpty(Queue q);/* 是否满 */int isFull(Queue q);/* 创建队列 */Queue createQueue(int maxElement);/* 销毁队列 */void disposeQueue(Queue q);/* 置空 */void makeEmpty(Queue q);/* 入队 */void enQueue(ElemType x, Queue q);/* 出队 */ElemType deQueue( Queue q);#endif /* Queue_h */



(2)实现文件

////  Queue.c//  Unweighted////  Created by Wuyixin on 2017/6/6.//  Copyright © 2017年 Coding365. All rights reserved.//#include "Queue.h"/* 是否空 */int isEmpty(Queue q){    return q->size == 0;}/* 是否满 */int isFull(Queue q){    return q->front % (q->capacity) == (q->rear + 2) % q->capacity;}/* 创建队列 */Queue createQueue(int maxElement){    if (maxElement <= 0)        exit(EXIT_FAILURE);    Queue q = malloc(sizeof(struct QueueRecord));    if (q == NULL)        exit(EXIT_FAILURE);        ElemType* array = malloc(maxElement * sizeof(ElemType));    if (array == NULL)        exit(EXIT_FAILURE);    q->array = array;    q->capacity = maxElement + 1;    makeEmpty(q);    return q;}/* 销毁队列 */void disposeQueue(Queue q){    if (q != NULL){        free(q->array);        free(q);    }}/* 置空 */void makeEmpty(Queue q){    q->size = 0;    q->front = 1;    q->rear = 0;}/* 入队 */void enQueue(ElemType x, Queue q){    if (!isFull(q)){        q->rear = (q->rear + 1) % q->capacity;        q->size += 1;        q->array[q->rear] = x;    }}/* 出队 */ElemType deQueue(Queue q){    if (!isEmpty(q)){        int tmp = q->front;        q->front = (q->front + 1) % q->capacity;        q->size -= 1;        return q->array[tmp];    }        return INT_MIN;}



3.2 链表
(1)头文件
////  LinkList.h//  Unweighted////  Created by Wuyixin on 2017/6/6.//  Copyright © 2017年 Coding365. All rights reserved.//#ifndef LinkList_h#define LinkList_h#include <stdio.h>#include <limits.h>#include <stdlib.h>extern int UNAVAILABLE;typedef struct Node *LinkedList,*PtoNode;typedef int ElemType;struct Node{    ElemType data;    struct Node* next;    int dist;    int known;    int path;};/* 链表初始化 */LinkedList initList();/* 插入元素 */ElemType insert(ElemType x,LinkedList list);/* 删除链表 */void deleteList(LinkedList list);/* 打印链表 */void printList(LinkedList list);#endif /* LinkList_h */



(2)实现文件
////  LinkList.c//  Unweighted////  Created by Wuyixin on 2017/6/6.//  Copyright © 2017年 Coding365. All rights reserved.//#include "LinkList.h"int UNAVAILABLE = INT_MIN;/* 链表初始化 */LinkedList initList(){    LinkedList h = malloc(sizeof(struct Node));    if (h == NULL)        exit(EXIT_FAILURE);    h->next = NULL;    h->data = UNAVAILABLE;    return h;}/* 插入元素 */ElemType insert(ElemType x,LinkedList list){    PtoNode current;    current = list;    while (current->next != NULL)        current = current->next;            /* 生成新节点 */    PtoNode n = (PtoNode)malloc(sizeof(struct Node));    if (n == NULL)        exit(EXIT_FAILURE);        n->data = x;    n->next = NULL;        current->next = n;            return x;}/* 删除链表 */void deleteList(LinkedList list){    if (list == NULL)        return;    PtoNode node,old;    node = list;    while (node->next != NULL){        old = node;        node = node->next;        free(old);    }}/* 打印链表 */void printList(LinkedList list){    PtoNode node;    node = list->next;    while (node!= NULL ) {        printf("%d ",node->data);        node = node->next;    }    printf("\n");}





原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 子宫大怎么办能变小吗 子宫前壁肌瘤5.4怎么办 7个月孕妇得疱疹怎么办 受风脸上起疙瘩怎么办 受风了起疙瘩怎么办 7个月宝宝肠炎怎么办 出水痘发烧39度怎么办 腰肌拉伤怎么办恢复快 过敏起大水泡了怎么办 身上长疱疹怎么办冶疗 刚怀孕长了疱疹怎么办 吃完饭恶心想吐怎么办 减肥药吃了心慌怎么办 吃多了恶心想吐怎么办 想吐怎么办最快最有效 想吐又吐不出来怎么办 3岁宝宝反胃呕吐怎么办 2岁宝宝反胃呕吐怎么办 突然恶心想吐是怎么办 孕4个月反胃呕吐怎么办 怀孕2月反应大怎么办 狗吐拉稀不吃饭怎么办 狗狗咳喘怎么办最有效 半永久纹眉失败怎么办 纹的眉毛太细了怎么办 眉毛颜色做深了怎么办 半永久眼线不掉怎么办 移植9天来月经怎么办 月经迟迟不来该怎么办 lol晋级赛输了怎么办 激素正常的多囊怎么办 右侧输卵管通而不畅怎么办 小该咳嗽老不好怎么办 孩子吓着了怎么办最快 2个月宝宝吓到了怎么办 3个月宝宝吓到了怎么办 宝宝吓着了发烧怎么办 好几个月不遗精怎么办 孕妇吃了黑橄榄怎么办 内膜4mm来月经了怎么办 吃了伟哥没效果怎么办