算法導論代碼 第21章 用於不相交集合的數據結構

21章 用於不相交集合的數據結構

21.2 不相交集體的鏈表表示

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct set_type *set;
struct set_node {
	void *key;
	struct set_node *next;
	struct set_node *representative;	//指向代表的集合元素
};

struct set_type {
	struct set_node *head;
	struct set_node *tail;
	int num;
};
void set_node_ini(struct set_node *x, void *key)
{
	x->key = key;
	x->next = NULL;
	x->representative = NULL;
}

set set_create(void *key)
{
	set s = malloc(sizeof(struct set_type));
	struct set_node *x = malloc(sizeof(struct set_node));
	set_node_ini(x, key);
	s->head = x;
	s->tail = x;
	s->num = 1;
	x->representative = x;
	return s;
}

struct set_node *find_set(set s)
{
	return s->head->representative;
}

void update_representative(struct set_node *head,
			   struct set_node *representative)
{
	struct set_node *p = head;
	while (p != NULL) {
		p->representative = representative;
		p = p->next;
	}
}

//把較短的鏈表拼到較長的鏈表上,更新短鏈表的每個結點指向代表指針
void set_union(set sa, set sb)
{
	if (sa->num < sb->num) {
		update_representative(sa->head, sb->head);
		sb->tail->next = sa->head;
		sa->head = sb->head;
	} else {
		update_representative(sb->head, sa->head);
		sa->tail->next = sb->head;
		sa->tail = sb->tail;
	}
	sa->num += sb->num;
}

void set_destroy(set s, void (*free_key) (void *))
{
	free_key(s->head->key);
	free(s->head);
	free(s);
}

struct edge {
	char u;
	char v;
};
int main()
{
	//數據根據書上圖21-1
	char vertex[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' };
	set s[256] = { NULL };
	struct edge edge_array[] = { {'b', 'd'}, {'e', 'g'}, {'a', 'c'},
	{'h', 'i'}, {'a', 'b'}, {'e', 'f'}, {'b', 'c'}
	};
	int vertex_num = sizeof(vertex) / sizeof(vertex[0]);
	for (int i = 0; i < vertex_num; i++) {
		char *c = malloc(sizeof(char));
		*c = vertex[i];
		s[(int)vertex[i]] = set_create(c);
	}
	//計算連通子圖
	for (unsigned i = 0; i < sizeof(edge_array) / sizeof(edge_array[0]);
	     i++) {
		set su = s[(int)edge_array[i].u];
		set sv = s[(int)edge_array[i].v];
		if (find_set(su) != find_set(sv)) {
			set_union(su, sv);
		}
	}
	//輸出連通子圖
	char str_set[256][256] = { {0} };
	for (int i = 0; i < vertex_num; i++) {
		char *pc = find_set(s[(int)vertex[i]])->key;
		int len = strlen(str_set[(int)*pc]);
		str_set[(int)*pc][len] = vertex[i];
	}
	printf("輸出不相交集合組:\n");
	for (int i = 0; i < vertex_num; i++) {
		if (strcmp(str_set[(int)vertex[i]], "") != 0) {
			printf("%s\n", str_set[(int)vertex[i]]);
		}
	}
	for (int i = 0; i < vertex_num; i++) {
		set sv = s[(int)vertex[i]];
		set_destroy(sv, free);
	}
	return 0;
}

21.3 不相交集合森林

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct set_type *set;
struct set_node {
	void *key;
	int rank;
	struct set_node *parent;
};

void set_node_ini(struct set_node *x, void *key)
{
	x->key = key;
	x->rank = 0;
	x->parent = NULL;
}

struct set_type {
	struct set_node *root;
};

set set_create(void *key)
{
	set s = malloc(sizeof(struct set_type));
	s->root = malloc(sizeof(struct set_node));
	set_node_ini(s->root, key);
	s->root->parent = s->root;
	s->root->rank = 0;
	return s;
}

void link(struct set_node *x, struct set_node *y)
{
	if (x->rank > y->rank) {
		y->parent = x;
	} else {
		x->parent = y;
		if (x->rank == y->rank) {
			++y->rank;
		}
	}
}

struct set_node *find_set_path_compression(struct set_node *x)
{
	if (x != x->parent) {
		x->parent = find_set_path_compression(x->parent);
	}
	return x->parent;
}

struct set_node *find_set(set s)
{
	return find_set_path_compression(s->root);
}

void set_destroy(set s, void (*free_key) (void *))
{
	free_key(s->root->key);
	free(s->root);
	free(s);
}

void set_union(set sa, set sb)
{
	link(find_set(sa), find_set(sb));
}

struct edge {
	char u;
	char v;
};
int main()
{
	//數據根據書上圖21-1
	char vertex[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' };
	set s[256] = { NULL };
	struct edge edge_array[] = { {'b', 'd'}, {'e', 'g'}, {'a', 'c'},
	{'h', 'i'}, {'a', 'b'}, {'e', 'f'}, {'b', 'c'}
	};
	int vertex_num = sizeof(vertex) / sizeof(vertex[0]);
	for (int i = 0; i < vertex_num; i++) {
		char *c = malloc(sizeof(char));
		*c = vertex[i];
		s[(int)vertex[i]] = set_create(c);
	}
	//計算連通子圖
	for (unsigned i = 0; i < sizeof(edge_array) / sizeof(edge_array[0]);
	     i++) {
		set su = s[(int)edge_array[i].u];
		set sv = s[(int)edge_array[i].v];
		if (find_set(su) != find_set(sv)) {
			set_union(su, sv);
		}
	}
	//輸出連通子圖
	char str_set[256][256] = { {0} };
	for (int i = 0; i < vertex_num; i++) {
		char *pc = find_set(s[(int)vertex[i]])->key;
		int len = strlen(str_set[(int)*pc]);
		str_set[(int)*pc][len] = vertex[i];
	}
	printf("輸出不相交集合組:\n");
	for (int i = 0; i < vertex_num; i++) {
		if (strcmp(str_set[(int)vertex[i]], "") != 0) {
			printf("%s\n", str_set[(int)vertex[i]]);
		}
	}
	for (int i = 0; i < vertex_num; i++) {
		set sv = s[(int)vertex[i]];
		set_destroy(sv, free);
	}
	return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章