00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <errno.h>
00027 #include <stdlib.h>
00028 #include <sys/types.h>
00029 #include "disjoint_set.h"
00030 #include "debug.h"
00031
00032 struct disjoint_set {
00033 size_t *parent;
00034 size_t *rank;
00035 size_t size;
00036 };
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 static void link_sets(disjoint_set_t *ds, size_t set1, size_t set2)
00050 {
00051 size_t rank1 = ds->rank[set1];
00052 size_t rank2 = ds->rank[set2];
00053
00054 if (rank1 > rank2)
00055 ds->parent[set2] = set1;
00056 else {
00057 ds->parent[set1] = set2;
00058 if (rank1 == rank2)
00059 ds->rank[set2] += 1;
00060 }
00061 }
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 static size_t find_set(disjoint_set_t *ds, size_t id)
00072 {
00073 if (id != ds->parent[id])
00074 ds->parent[id] = find_set(ds, ds->parent[id]);
00075
00076 return ds->parent[id];
00077 }
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 int disjoint_set_new(disjoint_set_t **ds, size_t size)
00095 {
00096 if (ds == NULL)
00097 return_error(EINVAL);
00098
00099 disjoint_set_t *p = malloc(sizeof *p);
00100 if (p == NULL)
00101 return_error(ENOMEM);
00102
00103 p->parent = malloc(size * sizeof *p->parent);
00104 if (p->parent == NULL) {
00105 free(p);
00106 return_error(ENOMEM);
00107 }
00108
00109 p->rank = calloc(size, sizeof *p->rank);
00110 if (p->rank == NULL) {
00111 free(p->parent);
00112 free(p);
00113 return_error(ENOMEM);
00114 }
00115
00116 p->size = size;
00117
00118 size_t i;
00119 for(i = 0; i < size; i++)
00120 p->parent[i] = i;
00121
00122 *ds = p;
00123
00124 return 0;
00125 }
00126
00127
00128
00129
00130
00131
00132
00133
00134 int disjoint_set_free(disjoint_set_t *ds)
00135 {
00136 if (ds == NULL)
00137 return_error(EINVAL);
00138
00139 free(ds->parent);
00140 free(ds->rank);
00141
00142 free(ds);
00143
00144 return 0;
00145 }
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 int disjoint_set_union(disjoint_set_t *ds, size_t elem1, size_t elem2)
00157 {
00158 if (ds == NULL || elem1 >= ds->size || elem2 >= ds->size)
00159 return_error(EINVAL);
00160
00161 size_t set1;
00162 size_t set2;
00163
00164 disjoint_set_find(ds, &set1, elem1);
00165 disjoint_set_find(ds, &set2, elem2);
00166
00167 link_sets(ds, set1, set2);
00168
00169 return 0;
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 int disjoint_set_find(disjoint_set_t *ds, size_t *set, size_t elem)
00182 {
00183 if (ds == NULL || set == NULL || elem >= ds->size)
00184 return_error(EINVAL);
00185
00186 *set = find_set(ds, elem);
00187
00188 return 0;
00189
00190 }
00191