1 算法介绍
如果图具有负边值,那么Dijkstra算法行不通。但是把赋权的和无权的算法结合起来将会解决这个问题。开始,我们把s放到队列中。然后,在每个阶段我们让一个顶点出队。找出所有与v邻接的顶点w,使得dw > dv + cvw。然后更新dw和pw,并在w不在队列中的时候把它放到队列中。
2 算法实现
//
// main.c
// WeightedNegative
//
// 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;
g[i].cost = 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;
w->cost = a[i][j];
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 weightedNegative(Graph g,int n,int start){
Queue q;
Vertex v,w;
q = createQueue(n);
makeEmpty(q);
g[start].dist = 0;
enQueue(start, q);
while (!isEmpty(q)) {
v = &g[deQueue(q)];
v->known = 1;
for (w = v->next; w != NULL; w = w->next) {
/* 找到比原来更短的距离,更新距离 */
if (g[w->data].dist > v->dist + w->cost){
g[w->data].dist = v->dist + w->cost;
/* 更新path */
g[w->data].path = v->data;
if(!g[w->data].known)
enQueue(w->data, q);
}
}
}
disposeQueue(q);
}
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] = 2;
a[0][3] = 1;
a[1][3] = 3;
a[1][4] = -10;
a[2][0] = 4;
a[2][5] = 5;
a[3][2] = 2;
a[3][4] = 2;
a[3][5] = 8;
a[3][6] = 4;
a[4][6] = 6;
a[6][5] = 1;
Graph g;
g = initGraph(7, a);
weightedNegative(g, 7, 0);
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 */
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;/* 上一个顶点 */
int cost;/* 值 */
};
/* 链表初始化 */
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");
}