#include <stdio.h>
#include <malloc.h>
#define true 1
#define false 0
#define INFINITY 1000000
#define MaxVertexNum 10000
#define MaxArcNum 100000
int Visite[MaxVertexNum];
struct ArcStruct {
int v1, v2, dist;
};
struct GraphStruct {//创建一个最简单的无向图
int vexnum, arcnum;
int dist[MaxArcNum];
};
struct MinHeapStruct {
int size;
struct ArcStruct a[MaxArcNum];
};
typedef struct GraphStruct* Graph;
typedef struct MinHeapStruct* MinHeap;
typedef struct ArcStruct* Edge;
Graph createGraph();
void initializeGraph( Graph G );
int prim( Graph G, int u );
void swap( int *p1, int *p2 );
int computeNum( int a );
void assignEdge( Edge e, int v1, int v2, int dist );
Edge deleteMinHeap( MinHeap h );
void insertMinHeap( MinHeap h, Edge e );
void swapHeapNode ( Edge e1, Edge e2 );
void assignHeapNode( Edge e1, Edge e2 );
int main( void ) {
Graph G = createGraph();
int i = 0;
int V1, V2;
int dist;
int num = 0;
FILE *fp = fopen("kruskal2.txt", "r");
int mindist = 0;
for( i = 0; i < G->arcnum; i++ ) {
fscanf(fp, "%d %d %d", &V1, &V2, &dist);
if( V1 < V2 ) {
swap( &V1, &V2 );
}
num = computeNum( V1-1 ) + V2-1;
G->dist[num] = dist;
}
//printf("%d %d", G->dist[19], G->dist[20]);
mindist = prim( G, 0 );
//printf("%d", mindist);
return 0;
}
Graph createGraph() {
Graph G = ( Graph )malloc( sizeof( struct GraphStruct ) );
initializeGraph( G );
return G;
}
void initializeGraph( Graph G ) {
int i = 0;
int n = 0;
FILE* fp = fopen("kruskal1.txt", "r");
fscanf(fp, "%d %d", &G->vexnum, &G->arcnum);
n = computeNum( G->vexnum );
for( i = 0; i < n; i++ ) {
G->dist[i] = INFINITY;
}
for( i = 0; i < G->vexnum; i++ ) {
Visite[i] = false;//好像这里也可以提出来一个函数
}
}
int prim( Graph G, int u ) {
MinHeap h = ( MinHeap )malloc( sizeof(struct MinHeapStruct) );
h->size = 0;
h->a[0].dist = -INFINITY;
Visite[u] = true;
int mindist = 0;
Edge e = ( Edge )malloc( sizeof(struct ArcStruct) );
//make all edges of u into h
int num, i;
num = computeNum( u );
for( i = 0; i < u; i++ ) {
if( G->dist[num] != INFINITY ) {
assignEdge( e, u, i, G->dist[num] );
insertMinHeap( h, e );
}
num++;
}
for( i = u+1; i < G->vexnum; i++ ) {
num = computeNum( i ) + u;
if( G->dist[num] != INFINITY ) {
assignEdge( e, u, i, G->dist[num] );
insertMinHeap( h, e );
}
}
//next: MinHeap brings minest dist out, until empty.
while( h->size != 0 ) {// deleteHeap only returns one element, so union what need
e = deleteMinHeap( h );
if( !Visite[e->v2] ) {
//make all edges of e->v2 into h
u = e->v2;
Visite[u] = true;
mindist += e->dist;
num = computeNum( u );
for( i = 0; i < u; i++ ) {
if( G->dist[num] != INFINITY && !Visite[i] ) {
assignEdge( e, u, i, G->dist[num] );
insertMinHeap( h, e );
}
num++;
}
for( i = u+1; i < G->vexnum; i++ ) {
num = computeNum( i ) + u;
if( G->dist[num] != INFINITY && !Visite[i] ) {
assignEdge( e, u, i, G->dist[num] );
insertMinHeap( h, e );
}
}
}
}
return mindist;
}
void assignEdge( Edge e, int v1, int v2, int dist ) {
e->v1 = v1;
e->v2 = v2;
e->dist = dist;
}
void insertMinHeap( MinHeap h, Edge e ) {
if( h->size == 0 ) {
assignHeapNode( &(h->a[++h->size]), e );
return;
}
h->size++;
int parent, child = h->size;
assignHeapNode( &(h->a[child]), e );
for( parent = h->size/2; parent >= 1; parent = child/2 ) {
if( h->a[parent].dist <= h->a[child].dist ) { break; }
swapHeapNode( &h->a[parent], &h->a[child] );
child = parent;
}
}
Edge deleteMinHeap( MinHeap h ) {
Edge e = ( Edge )malloc( sizeof(struct ArcStruct) );
assignHeapNode( e, &(h->a[1]) );
assignHeapNode( &(h->a[1]), &(h->a[h->size]) );
h->size--;
int parent, child;
for( parent = 1; parent*2 <= h->size; parent = child ) {
child = parent*2;
if( child < h->size && (h->a[child+1].dist < h->a[child].dist) ) { child++; }
if( h->a[parent].dist <= h->a[child].dist ) { break; }
swapHeapNode( &(h->a[parent]), &(h->a[child]) );
}
return e;
}
void assignHeapNode( Edge e1, Edge e2 ) {
e1->dist = e2->dist;
e1->v1 = e2->v1;
e1->v2 = e2->v2;
}
void swapHeapNode ( Edge e1, Edge e2 ) {
Edge e3 = ( Edge )malloc( sizeof( struct ArcStruct) );
assignHeapNode( e3, e2 );
assignHeapNode( e2, e1 );
assignHeapNode( e1, e3 );
}
int computeNum( int a ) {
return a*(a-1)/2;
}
void swap( int *p1, int *p2 ) {
int tmp = 0;
tmp = *p2;
*p2 = *p1;
*p1 = tmp;
}
水平太低了。写得很慢。Prim中间有一段没有优化,但是,我知道了,用邻接表不好写(反正我是没写出来),如果是无向图的话我认为最好还是用一维数组的无向图再加上这个算法。其中过程容易错,唉。不多说。
用一维数组的无向图写Prim算法(用最小堆优化)
最新推荐文章于 2024-05-11 10:34:06 发布