unionfind.h
Go to the documentation of this file.
1 /* Copyright (C) 2013-2016, The Regents of The University of Michigan.
2 All rights reserved.
3 This software was developed in the APRIL Robotics Lab under the
4 direction of Edwin Olson, ebolson@umich.edu. This software may be
5 available under alternative licensing terms; contact the address above.
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8 1. Redistributions of source code must retain the above copyright notice, this
9  list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright notice,
11  this list of conditions and the following disclaimer in the documentation
12  and/or other materials provided with the distribution.
13 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 The views and conclusions contained in the software and documentation are those
24 of the authors and should not be interpreted as representing official policies,
25 either expressed or implied, of the Regents of The University of Michigan.
26 */
27 
28 #pragma once
29 
30 #include <stdint.h>
31 #include <stdlib.h>
32 
33 typedef struct unionfind unionfind_t;
34 
35 struct unionfind
36 {
37  uint32_t maxid;
38  struct ufrec *data;
39 };
40 
41 struct ufrec
42 {
43  // the parent of this node. If a node's parent is its own index,
44  // then it is a root.
45  uint32_t parent;
46 
47  // for the root of a connected component, the number of components
48  // connected to it. For intermediate values, it's not meaningful.
49  uint32_t size;
50 };
51 
52 static inline unionfind_t *unionfind_create(uint32_t maxid)
53 {
54  unionfind_t *uf = (unionfind_t*) calloc(1, sizeof(unionfind_t));
55  uf->maxid = maxid;
56  uf->data = (struct ufrec*) malloc((maxid+1) * sizeof(struct ufrec));
57  for (uint32_t i = 0; i <= maxid; i++) {
58  uf->data[i].size = 1;
59  uf->data[i].parent = i;
60  }
61  return uf;
62 }
63 
64 static inline void unionfind_destroy(unionfind_t *uf)
65 {
66  free(uf->data);
67  free(uf);
68 }
69 
70 /*
71 static inline uint32_t unionfind_get_representative(unionfind_t *uf, uint32_t id)
72 {
73  // base case: a node is its own parent
74  if (uf->data[id].parent == id)
75  return id;
76 
77  // otherwise, recurse
78  uint32_t root = unionfind_get_representative(uf, uf->data[id].parent);
79 
80  // short circuit the path. [XXX This write prevents tail recursion]
81  uf->data[id].parent = root;
82 
83  return root;
84 }
85 */
86 
87 // this one seems to be every-so-slightly faster than the recursive
88 // version above.
89 static inline uint32_t unionfind_get_representative(unionfind_t *uf, uint32_t id)
90 {
91  uint32_t root = id;
92 
93  // chase down the root
94  while (uf->data[root].parent != root) {
95  root = uf->data[root].parent;
96  }
97 
98  // go back and collapse the tree.
99  while (uf->data[id].parent != root) {
100  uint32_t tmp = uf->data[id].parent;
101  uf->data[id].parent = root;
102  id = tmp;
103  }
104 
105  return root;
106 }
107 
108 static inline uint32_t unionfind_get_set_size(unionfind_t *uf, uint32_t id)
109 {
110  uint32_t repid = unionfind_get_representative(uf, id);
111  return uf->data[repid].size;
112 }
113 
114 static inline uint32_t unionfind_connect(unionfind_t *uf, uint32_t aid, uint32_t bid)
115 {
116  uint32_t aroot = unionfind_get_representative(uf, aid);
117  uint32_t broot = unionfind_get_representative(uf, bid);
118 
119  if (aroot == broot)
120  return aroot;
121 
122  // we don't perform "union by rank", but we perform a similar
123  // operation (but probably without the same asymptotic guarantee):
124  // We join trees based on the number of *elements* (as opposed to
125  // rank) contained within each tree. I.e., we use size as a proxy
126  // for rank. In my testing, it's often *faster* to use size than
127  // rank, perhaps because the rank of the tree isn't that critical
128  // if there are very few nodes in it.
129  uint32_t asize = uf->data[aroot].size;
130  uint32_t bsize = uf->data[broot].size;
131 
132  // optimization idea: We could shortcut some or all of the tree
133  // that is grafted onto the other tree. Pro: those nodes were just
134  // read and so are probably in cache. Con: it might end up being
135  // wasted effort -- the tree might be grafted onto another tree in
136  // a moment!
137  if (asize > bsize) {
138  uf->data[broot].parent = aroot;
139  uf->data[aroot].size += bsize;
140  return aroot;
141  } else {
142  uf->data[aroot].parent = broot;
143  uf->data[broot].size += asize;
144  return broot;
145  }
146 }
static unionfind_t * unionfind_create(uint32_t maxid)
Definition: unionfind.h:52
struct ufrec * data
Definition: unionfind.h:38
static uint32_t unionfind_get_representative(unionfind_t *uf, uint32_t id)
Definition: unionfind.h:89
static uint32_t unionfind_get_set_size(unionfind_t *uf, uint32_t id)
Definition: unionfind.h:108
static uint32_t unionfind_connect(unionfind_t *uf, uint32_t aid, uint32_t bid)
Definition: unionfind.h:114
static void unionfind_destroy(unionfind_t *uf)
Definition: unionfind.h:64
uint32_t maxid
Definition: unionfind.h:37
uint32_t parent
Definition: unionfind.h:45
uint32_t size
Definition: unionfind.h:49


apriltag
Author(s): Edwin Olson , Max Krogius
autogenerated on Mon Jun 26 2023 02:26:35