PRIM 算法

根据算法导论里给出的算法实现。

#include 

#define MAX_VERTEX_NUM	100
#define MAX_EDGE_NUM	80

struct vertex
{
	int key;
	int id;
	int parent;
};

struct  edge
{
	int weight;
	int v;
};

struct edge edges[MAX_VERTEX_NUM][MAX_EDGE_NUM];
struct vertex min_spanning_tree[MAX_VERTEX_NUM];
int degree[MAX_VERTEX_NUM];
int result[MAX_VERTEX_NUM];
int result_index;
int number_of_vertices, number_of_edges;

int mapping[MAX_VERTEX_NUM]; //id --> heap index


void read_data(void)
{
	scanf("%d %d", &number_of_vertices, &number_of_edges);
	
	int i;
	for(i = 0; i < number_of_edges; i++)
	{
		int s, d, w;
		scanf("%d %d %d", &s, &d, &w);
		edges[s][degree[s]].v = d;
		edges[s][degree[s]].weight = w;
		degree[s]++;
	}
}


void init_data(void)
{
	int i;
	for(i = 1; i <= number_of_vertices; i++)
	{
		min_spanning_tree[i].key = (unsigned int)(1 << 31) - 1;
		min_spanning_tree[i].id = i;
		min_spanning_tree[i].parent = -1;
		mapping[i] = i;
	}
}

///////////////////////////mini heap//////////////////////

int min_heap_size;
int min_heap_capacity;

void min_heap_init(int capacity)
{
	min_heap_capacity = capacity;
}

void min_heap_heapify(struct vertex	min_spanning_tree[], int index)
{
	int left = 2 * index;
	int right = left + 1;

	int min;
	if(left <= min_heap_size &&	min_spanning_tree[left].key < min_spanning_tree[index].key)
	{
		min = left;
	}
	else
	{
		min = index;
	}

	if(right <= min_heap_size && min_spanning_tree[right].key < min_spanning_tree[index].key)
	{
		min = right;
	}

	if(min != index)
	{
		struct vertex t = min_spanning_tree[min];
		min_spanning_tree[min] = min_spanning_tree[index];
		mapping[min_spanning_tree[index].id] = min;
		min_spanning_tree[index] = t;
		mapping[t.id] = index;
	}
}


void min_heap_build(struct vertex min_spanning_tree[])
{
	min_heap_size = min_heap_capacity;

	int i;
	for(i = min_heap_size / 2; i>= 1; i--)
	{
		min_heap_heapify(min_spanning_tree, i);
	}
}


struct vertex  min_heap_extract(struct vertex min_spanning_tree[])
{
	if( min_heap_size <= 0)
	{
		printf("underflow...\n");
	}

	struct vertex t = min_spanning_tree[1];
	min_spanning_tree[1] = min_spanning_tree[min_heap_size];
	mapping[min_spanning_tree[min_heap_size].id] = 1;
	mapping[t.id] = -1;
	min_heap_size = min_heap_size - 1;
	min_heap_heapify(min_spanning_tree, 1);
	return t;
}

void min_heap_decrease_key(struct vertex min_spanning_tree[], int index, int key)
{
	if( key > min_spanning_tree[index].key)
	{
		printf("key is large\n");
		return;
	}

	min_spanning_tree[index].key = key;
	
	int i = index;
	while( i > 1 && min_spanning_tree[i/2].key > key)
	{
		struct vertex t;
		t = min_spanning_tree[i];
		min_spanning_tree[i] =	min_spanning_tree[i/2];
		mapping[min_spanning_tree[i/2].id] = i;
		min_spanning_tree[i/2] = t;
		mapping[t.id] = i/2;

		i = i/2;
	}
}

int min_heap_length(void)
{
	return min_heap_size;
}
////////////////////////////////////////////////////////////


void mst_prim(int root)
{
	init_data();
	
	min_spanning_tree[root].key = 0;

	min_heap_init(number_of_vertices);
	min_heap_build(min_spanning_tree);

	int cost = 0;
	while(min_heap_length() > 0)
	{
		struct vertex min = min_heap_extract(min_spanning_tree);
		
		result[result_index] = min.id;
		result_index++;
		cost += min.key;
		int i;
		for(i = 0; i < degree[min.id]; i++)
		{
			int u = edges[min.id][i].v;
			int weight = edges[min.id][i].weight;

			//if mapping[u] is -1, it means the vertex u has been put into the MST.
			if(mapping[u] != -1 && min_spanning_tree[mapping[u]].key > weight)
			{
				min_heap_decrease_key(min_spanning_tree, mapping[u], weight);
				min_spanning_tree[mapping[u]].parent = min.id;
			}
		}
	}
	printf("minimal cost: %d\n", cost);
}

int main(void)
{
	read_data();
	mst_prim(1);
	return 0;	
}


测试数据:

9 28
1 2 4
2 1 4
2 3 8
3 2 8
3 4 7
4 3 7
4 5 9
5 4 9
5 6 10
6 5 10
6 7 2
7 6 2
7 8 1
8 7 1
8 9 7 
9 8 7
1 8 8
8 1 8
7 9 6
9 7 6
2 8 11
8 2 11
3 9 2
9 3 2
3 6 4
6 3 4
4 6 14
6 4 14

结果:

$ ./prim  < input.txt 
minimal cost: 37


你可能感兴趣的:(Algorithms)