A detailed _c language based on the Johnson algorithm on sparse graphs

Source: Internet
Author: User
Tags int size prev

Algorithm steps Brief:

1. Figure G After the addition of the new node in Figure G, add the new node 0 to the distance between all the original nodes is 0, and form a new edge set E ';

2. Use the Bellman-ford algorithm to process G ' and form the minimum distance d of 0 nodes to each node.

3. If the Bellman-ford algorithm detects that there is a negative weight loop, the hint false and exit, otherwise continue.

4. For vertex v in all G ', set H (v) to this value based on the minimum distance of 0 nodes to V.

5. For all side W (u,v), the weight value is updated to W (u,v) +h (U)-H (v)

6. Dijkstra algorithm for all nodes in Fig G calculates the shortest distance from other vertices d ' [u][v]

(This assumes that the G and W sets are stored separately.) The direct use of G ' can also be possible, since 0 nodes are not up to other nodes, but this obviously wastes computational time. If the weight information exists in G ', it can operate on G ', only skipping the processing of 0 nodes.

7. Original g medium shortest distance d[u][v] = d ' [u][v] +h (v)-H (U)

Some places in the code are not optimized, such as the auxiliary structure vassist in fact, in the Bellman-ford algorithm and Dijkstra algorithm two functions in a slightly different usage, and the member variable in the former only used 2, and relaxation algorithm relax also have a similar situation. The former is a simple reuse, the latter is directly differentiated by name.

  The code contains three parts: The Bellman-ford algorithm, the Dijkstra algorithm, the priority series group implemented with two-item heap (Dijkstra algorithm to use). the following is the C language version of the algorithm, test examples and "Introduction to the algorithm" figure 25-1

Copy Code code as follows:

#include <stdio.h>
#include <stdlib.h>

#define U 65535
#define PARENT (i) ((i-1)/2)
#define LEFT (i) (2* (i) +1)
#define RIGHT (i) (2* (i) +2)
#define N 5

struct Vertex {
int key;
struct vtable *adj;
};

struct Vtable {
int key;//This key is the ordinal number of the vertex array
struct Vertext *v;
int W;
struct vtable *next;
};

struct Vassist {
int D;
int p;
int key;
};


int insert (struct vertex *,int,int,int,int);
int walk (struct vertex *,int,int);
struct vassist *initialize_ss (int,int);
int relaxd (int *,int, int, int);
int relaxb (struct vassist *,int, int, int);
int build_min_heap (struct vassist *,int);
int min_heapify (struct vassist *, int, int);
int heap_extract_min (struct vassist *,int);
int inheap (struct vassist *,int, int);
int heap_decrease (struct vassist *,int, int);
int Dijkstra (struct vertex *,int,int,int * *);
int Bellman_ford (struct vertex *,int*, int,int);

int insert (struct vertex *p,int len,int i,int j,int W) {
struct vtable *q,*prev;
Q = P[i].adj;
printf ("key:%d\n", P[i].key);
prev = NULL;
while (Q!=null) {
if (Q->key = = j) {
printf ("Error:v%d to%d already exist.\n", i,j);
return 0;
}
else {
prev = q;
q=q->next;
}
}
Q = (struct vtable*) malloc (sizeof (struct vtable));
Q->key = j;
Q->w = W;
Q->next = NULL;
if (prev!=null)
Prev->next = q;
Else
P[i].adj = q;
return 1;
}

int walk (struct vertex *p,int len,int i) {
struct vtable *q = P[i].adj;
while (Q!=null) {
printf ("%d,w is%d\n", q->key,q->w);
q=q->next;
}
printf ("\ n");
}

struct vassist *initialize_ss (int size,int s) {
int i;
struct Vassist *va;
VA = (struct vassist *) malloc (size*sizeof (struct vassist));
for (i=0;i<size;i++) {
Va[i].key = i;//I!=key after building a heap
VA[I].D = U;
VA[I].P =-1;
}
VA[S].D = 0;
Return VA;
}

Relax for Dijkstra
int relaxd (int *p,int u,int v,int w) {//w=w (u,v)
if (p[v]>p[u]+w) {
P[V] = p[u]+w;
For simple processing, p uses an array
No parental markers.
If you want to mark with your parents, change p to a custom structure
}
return 1;
}

//relax for Beltman_ford
int relaxb (struct vassist *va,int u,int v,int w) {//w=w (u,v)
    if (va[ V].D>VA[U].D+W) {
        va[v].d = va[u].d+w;
        va[v].p = u;
   }
    return 1;
}


int Bellman_ford (struct vertex *graph,int *h,int size,int s) {//algorithm requires a negative-weight loop that does not contain source points
    int i,j;
    struct vtable *p;
    struct vassist *va;
    va = initialize_ss (size,s);
    for (i=1;i<size;i++)
        for (j=0;j<size-1; J + +) {
            p = Graph[j].adj;
            while (p!=null) {
                 RELAXB (VA,J,P->KEY,P->W);
                p=p->next;
           }
       }

printf ("From%d,\n", s);
for (j=0;j<size;j++)
printf ("To%d:%d\n", J,VA[J].D);

for (j=0;j<size;j++) {//0 node unnecessary
p = Graph[j].adj;
while (P!=null) {
if (va[p->key].d>va[j].d+p->w)
return 0;
p = p->next;
}
}
for (j=1;j<=size;j++)
H[J] = VA[J].D;
Free (VA);
H[0] = 0;
return 1;
}

int build_min_heap (struct vassist *va,int size) {//Build heap
int i;
for (i =size/2-1; i>=0; i--)
Min_heapify (va,i,size);

return 1;
}


int min_heapify (struct vassist *va, int i,int heap_size) {
int l,r,min;
struct Vassist temp;
int tmin = U;
L = left (i);
R = Right (i);
if ((L < heap_size) && (VA[L].D&LT;VA[I].D)) {
min = l;
Tmin = VA[L].D;
}
else {
min = i;
Tmin = VA[I].D;
}
if ((R < heap_size) && (VA[R].D&LT;VA[MIN].D)) {
min = r;
Tmin = VA[R].D;
}
if (!) ( min = i)) {
TEMP.D = VA[MIN].D;
TEMP.P = VA[MIN].P;
Temp.key = Va[min].key;

VA[MIN].D = VA[I].D;
VA[MIN].P = VA[I].P;
Va[min].key = Va[i].key;

VA[I].D = TEMP.D;
VA[I].P = TEMP.P;
Va[i].key = Temp.key;

Min_heapify (va,min,heap_size);
}
return 1;
}

int heap_extract_min (struct vassist *va,int heap_size) {
int min;
if (heap_size<1)
return-1;
min = Va[0].key;
VA[0].P = VA[HEAP_SIZE-1].P;
VA[0].D = VA[HEAP_SIZE-1].D;
Va[0].key = Va[heap_size-1].key;
Heap_size = heap_size-1;
Min_heapify (va,0,heap_size);
return min;
}

int inheap (struct vassist *va,int heap_size,int j) {
int i;
for (i=0;iif (Va[i].key = j)
return i;
return-1;
}

int heap_decrease (struct vassist *va,int i,int key_new) {
struct Vassist temp;
if (KEY_NEW&GT;VA[I].D)
return 0;
VA[I].D = key_new;
while ((i>0) && (va[parent (i)].d > Va[i].d)) {
TEMP.D = VA[I].D;
TEMP.P = VA[I].P;
Temp.key = Va[i].key;
VA[I].D = Va[parent (i)].d;
VA[I].P = Va[parent (i)].p;
Va[i].key = Va[parent (i)].key;
Va[parent (i)].d = TEMP.D;
Va[parent (i)].P = TEMP.P;
Va[parent (i)].key = Temp.key;
i = PARENT (i);
}
return 1;
}

int Dijkstra (struct vertex *graph,int len,int s,int) {
int i,j,heap_size;
struct vtable *q;
struct Vassist *va;
int *p;
p = (int *) malloc (len * sizeof (int));
for (i=0;i<len;i++)
P[i] = U;
P[s] = 0;
Heap_size = Len;

VA = initialize_ss (len,s);
Build_min_heap (va,heap_size);//va is taken to build a heap, the subsequent output distance can not be used again


while (heap_size>0) {
i = Heap_extract_min (va,heap_size);
printf ("node:%d\n", I);
heap_size--;
for (j=0;jprintf ("key:%d,d:%d, in array:%d\n", Va[j].key,va[j].d,p[va[j].key]);
Q = Graph[i].adj;
while (Q!=null) {
J=inheap (Va,heap_size,q->key);
if (j>=0)
if (va[j].d>p[i]+q->w)
Heap_decrease (VA,J,P[I]+Q-&GT;W);
Relaxd (P,I,Q-&GT;KEY,Q-&GT;W)//can actually merge Heap_decreas and relax, but not for interface simplicity
printf ("Relax%d to%d, W is%d\n", i,q->key,q->w);
Q = q->next;
}
for (j=0;jprintf ("key:%d,d:%d, in array:%d\n", Va[j].key,va[j].d,p[va[j].key]);
}
for (i=0;i<len;i++)
printf ("From%d to%d, distance is%d\n", s,i,p[i]);

Free (VA);

for (i=0;i<len;i++) {
Delta[s][i] = P[i];
}
Free (p);

}

int **johnson (struct vertex *g, int n) {
int i,j;
int *h,**delta,**d;
struct vertex *gn;
struct vtable *p;
gn = (struct vertex *) malloc (n*sizeof (struct vertex));
h = (int *) malloc (n*sizeof (int));
Delta = (int**) malloc (n*sizeof (int *));
D = (int**) malloc (n*sizeof (int *));
for (i=0;i<n;i++) {
delta[i]= (int*) malloc (n*sizeof (int));
d[i]= (int*) malloc (n*sizeof (int));
}
for (i=0;i<n;i++)
Gn[i] = G[i];

for (i=1;i<n;i++)
Insert (gn,n,0,i,0);
if (!bellman_ford (gn,h,n,0)) {
printf ("The input graph contains a negative-weight cycle.\n");
return NULL;
}

for (i=0;i<n;i++) {
p = Gn[i].adj;
while (P!=null) {
P->w = p->w+h[i]-h[p->key];
p=p->next;
}
}
for (i=0;i<n;i++)
Walk (Gn,n,i);

printf ("Before dijkstra\n");
for (i=1;i<n;i++) {
Dijkstra (Gn,n,i,delta);
for (j=1;j<n;j++)
D[I][J] = Delta[i][j] + h[j]-h[i];

}
for (i=1;i<n;i++) {
for (j=1;j<n;j++)
printf ("%d\t", D[i][j]);
printf ("\ n");
}
return D;
}

int main () {
int i,j;
int **d;
struct vertex vt[n+1];//as a 0-node entry reserve location
for (i=0;i<n+1;i++) {
Vt[i].adj = NULL;
Vt[i].key = i;
}

Insert (vt,n+1,1,2,3);
Insert (vt,n+1,1,3,8);
Insert (VT,N+1,1,5,-4);
Insert (vt,n+1,2,4,1);
Insert (vt,n+1,2,5,7);
Insert (vt,n+1,3,2,4);
Insert (VT,N+1,4,3,-5);
Insert (vt,n+1,4,1,2);
Insert (vt,n+1,5,4,6);
D = Johnson (vt,n+1);

return 1;
}


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.