Files
addr2line
adler
adler32
ahash
aho_corasick
angle
approx
backtrace
bitflags
blender
bytemuck
byteorder
case
cast_trait
cfg_if
chrono
color
color_quant
const_fn
crc32fast
crossbeam
crossbeam_channel
crossbeam_deque
crossbeam_epoch
crossbeam_queue
crossbeam_skiplist
crossbeam_utils
darling
darling_core
darling_macro
dds
deflate
densevec
derive_builder
derive_builder_core
dot
downcast_rs
dual_quat
either
erased_serde
failure
failure_derive
fixedbitset
float_cmp
fnv
freeimage
freeimage_sys
freetype
freetype_gl_sys
freetype_sys
freetypegl
futures
futures_channel
futures_core
futures_executor
futures_io
futures_macro
futures_sink
futures_task
futures_util
async_await
future
io
lock
sink
stream
task
fxhash
generational_arena
generic_array
getrandom
gif
gimli
glfw
glfw_sys
glin
glin_derive
glsl
half
harfbuzz
harfbuzz_ft_sys
harfbuzz_sys
hashbrown
human_sort
ident_case
image
indexmap
instant
itertools
itoa
jpeg_decoder
lazy_static
libc
libm
lock_api
log
lut_parser
matrixmultiply
memchr
memoffset
meshopt
miniz_oxide
monotonic_clock
mopa
mutiny_derive
na
nalgebra
base
geometry
linalg
ncollide3d
bounding_volume
interpolation
partitioning
pipeline
procedural
query
algorithms
closest_points
contact
distance
nonlinear_time_of_impact
point
proximity
ray
time_of_impact
visitors
shape
transformation
utils
nom
num_complex
num_cpus
num_integer
num_iter
num_rational
num_traits
numext_constructor
numext_fixed_uint
numext_fixed_uint_core
numext_fixed_uint_hack
object
once_cell
parking_lot
parking_lot_core
pathfinding
pennereq
petgraph
pin_project_lite
pin_utils
png
polygon2
ppv_lite86
proc_macro2
proc_macro_crate
proc_macro_hack
proc_macro_nested
quote
rand
rand_chacha
rand_core
rand_distr
raw_window_handle
rawpointer
rayon
rayon_core
rect_packer
regex
regex_syntax
retain_mut
rin
rin_app
rin_blender
rin_core
rin_gl
rin_graphics
rin_gui
rin_material
rin_math
rin_postpo
rin_scene
rin_util
rin_window
rinblender
rinecs
rinecs_derive
rinecs_derive_utils
ringui_derive
rustc_demangle
rusty_pool
ryu
scopeguard
seitan
seitan_derive
semver
semver_parser
serde
serde_derive
serde_json
shaderdata_derive
simba
slab
slice_of_array
slotmap
smallvec
std140_data
streaming_iterator
strsim
syn
synstructure
thiserror
thiserror_impl
thread_local
tiff
time
toml
typenum
unchecked_unwrap
unicode_xid
vec2
vec3
weezl
x11
zlib_sys
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//! Find minimum-spanning-tree in an undirected graph using
//! [Kruskal's algorithm](https://en.wikipedia.org/wiki/Kruskal's_algorithm).

use indexmap::IndexSet;
use std::hash::Hash;
use std::mem;

// Find parent and compress path by path halving.
fn find(parents: &mut [usize], mut node: usize) -> usize {
    while parents[node] != node {
        parents[node] = parents[parents[node]];
        node = parents[node];
    }
    node
}

#[test]
fn test_path_halving() {
    let mut parents = vec![0, 0, 1, 2, 3, 4, 5, 6];
    assert_eq!(find(&mut parents, 7), 0);
    assert_eq!(parents, vec![0, 0, 1, 1, 3, 3, 5, 5]);
    assert_eq!(find(&mut parents, 7), 0);
    assert_eq!(parents, vec![0, 0, 1, 0, 3, 3, 5, 3]);
    assert_eq!(find(&mut parents, 7), 0);
    assert_eq!(parents, vec![0, 0, 1, 0, 3, 3, 5, 0]);
    assert_eq!(find(&mut parents, 6), 0);
    assert_eq!(parents, vec![0, 0, 1, 0, 3, 3, 3, 0]);
    assert_eq!(find(&mut parents, 6), 0);
    assert_eq!(parents, vec![0, 0, 1, 0, 3, 3, 0, 0]);
}

fn union(parents: &mut [usize], ranks: &mut [usize], mut a: usize, mut b: usize) {
    if ranks[a] < ranks[b] {
        mem::swap(&mut a, &mut b);
    }
    parents[b] = a;
    if ranks[a] == ranks[b] {
        ranks[a] += 1;
    }
}

/// Minimal-spanning-tree for nodes with integer indices. The nodes must have
/// consecutives indices between 0 and `number_of_nodes`-1.
///
/// # Panics
///
/// This function panics if a node is outside the range [0, `number_of_nodes`-1].
pub fn kruskal_indices<C>(
    number_of_nodes: usize,
    edges: &[(usize, usize, C)],
) -> impl Iterator<Item = (usize, usize, C)>
where
    C: Clone + Ord,
{
    let mut parents = (0..number_of_nodes).collect::<Vec<_>>();
    let mut ranks = Vec::with_capacity(number_of_nodes);
    ranks.resize(number_of_nodes, 1);
    let mut edges = edges.to_vec();
    edges.sort_by(|a, b| a.2.cmp(&b.2));
    edges.into_iter().filter_map(move |(a, b, w)| {
        let ra = find(&mut parents, a);
        let rb = find(&mut parents, b);
        if ra != rb {
            union(&mut parents, &mut ranks, ra, rb);
            Some((a, b, w))
        } else {
            None
        }
    })
}

/// Find a minimum-spanning-tree. From a collection of
/// weighted edges, return a vector of edges forming
/// a minimum-spanning-tree.
pub fn kruskal<N, C>(edges: &[(N, N, C)]) -> impl Iterator<Item = (N, N, C)>
where
    N: Clone + Hash + Eq,
    C: Clone + Ord,
{
    let mut nodes = IndexSet::new();
    let edges = edges
        .iter()
        .map(|&(ref a, ref b, ref w)| {
            let ia = nodes.insert_full(a.clone()).0;
            let ib = nodes.insert_full(b.clone()).0;
            (ia, ib, w.clone())
        })
        .collect::<Vec<_>>();
    kruskal_indices(nodes.len(), &edges).map(move |(ia, ib, w)| {
        (
            nodes.get_index(ia).unwrap().clone(),
            nodes.get_index(ib).unwrap().clone(),
            w,
        )
    })
}