Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 650541d

Browse files
authoredMar 19, 2022
Add prufer-code (TheAlgorithms#289)
1 parent cce47ce commit 650541d

File tree

6 files changed

+133
-3
lines changed

6 files changed

+133
-3
lines changed
 

‎DIRECTORY.md

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
* [Dijkstra](https://github.com/TheAlgorithms/Rust/blob/master/src/graph/dijkstra.rs)
5252
* [Minimum Spanning Tree](https://github.com/TheAlgorithms/Rust/blob/master/src/graph/minimum_spanning_tree.rs)
5353
* [Prim](https://github.com/TheAlgorithms/Rust/blob/master/src/graph/prim.rs)
54+
* [Prufer Code](https://github.com/TheAlgorithms/Rust/blob/master/src/graph/prufer_code.rs)
5455
* [Lib](https://github.com/TheAlgorithms/Rust/blob/master/src/lib.rs)
5556
* Math
5657
* [Extended Euclidean Algorithm](https://github.com/TheAlgorithms/Rust/blob/master/src/math/extended_euclidean_algorithm.rs)

‎README.md

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ These are for demonstration purposes only.
3535
- [x] [Breadth-First Search (BFS)](./src/graph/breadth_first_search.rs)
3636
- [x] [Depth First Search (DFS)](./src/graph/depth_first_search.rs)
3737
- [x] [Bellman-Ford](./src/graph/bellman_ford.rs)
38+
- [x] [Prufer Code](./src/graph/prufer_code.rs)
3839

3940
## [Math](./src/math)
4041

‎src/dynamic_programming/maximal_square.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::cmp::min;
1010
/// Complexity
1111
/// - time complexity: O(n^2),
1212
/// - space complexity: O(n),
13-
pub fn maximal_square(matrix: &mut Vec<Vec<i32>>) -> i32 {
13+
pub fn maximal_square(matrix: &mut [Vec<i32>]) -> i32 {
1414
if matrix.is_empty() {
1515
return 0;
1616
}

‎src/graph/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod depth_first_search_tic_tac_toe;
55
mod dijkstra;
66
mod minimum_spanning_tree;
77
mod prim;
8+
mod prufer_code;
89

910
pub use self::bellman_ford::bellman_ford;
1011
pub use self::breadth_first_search::breadth_first_search;
@@ -13,3 +14,4 @@ pub use self::depth_first_search_tic_tac_toe::minimax;
1314
pub use self::dijkstra::dijkstra;
1415
pub use self::minimum_spanning_tree::kruskal;
1516
pub use self::prim::{prim, prim_with_start};
17+
pub use self::prufer_code::{prufer_decode, prufer_encode};

‎src/graph/prufer_code.rs

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
use std::collections::{BTreeMap, BTreeSet, BinaryHeap};
2+
3+
type Graph<V> = BTreeMap<V, Vec<V>>;
4+
5+
pub fn prufer_encode<V: Ord + Copy>(tree: &Graph<V>) -> Vec<V> {
6+
if tree.len() <= 2 {
7+
return vec![];
8+
}
9+
let mut result: Vec<V> = Vec::new();
10+
result.reserve(tree.len() - 2);
11+
let mut queue = BinaryHeap::new();
12+
let mut in_tree = BTreeSet::new();
13+
let mut degree = BTreeMap::new();
14+
for (vertex, adj) in tree {
15+
in_tree.insert(*vertex);
16+
degree.insert(*vertex, adj.len());
17+
if adj.len() == 1 {
18+
queue.push(*vertex);
19+
}
20+
}
21+
for _ in 2..tree.len() {
22+
let v = queue.pop().unwrap();
23+
in_tree.remove(&v);
24+
let u = tree[&v].iter().find(|u| in_tree.contains(u)).unwrap();
25+
result.push(*u);
26+
*degree.get_mut(u).unwrap() -= 1;
27+
if degree[u] == 1 {
28+
queue.push(*u);
29+
}
30+
}
31+
result
32+
}
33+
34+
fn add_directed_edge<V: Ord + Copy>(tree: &mut Graph<V>, a: V, b: V) {
35+
tree.entry(a).or_insert(vec![]).push(b);
36+
}
37+
38+
fn add_edge<V: Ord + Copy>(tree: &mut Graph<V>, a: V, b: V) {
39+
add_directed_edge(tree, a, b);
40+
add_directed_edge(tree, b, a);
41+
}
42+
43+
pub fn prufer_decode<V: Ord + Copy>(code: &[V], vertex_list: &[V]) -> Graph<V> {
44+
// For many cases, this function won't fail even if given unsuitable code
45+
// array. As such, returning really unlikely errors doesn't make much sense.
46+
let mut result = BTreeMap::new();
47+
let mut list_count: BTreeMap<V, usize> = BTreeMap::new();
48+
for vertex in code {
49+
*list_count.entry(*vertex).or_insert(0) += 1;
50+
}
51+
let mut queue = BinaryHeap::from(
52+
vertex_list
53+
.iter()
54+
.filter(|v| !list_count.contains_key(v))
55+
.cloned()
56+
.collect::<Vec<V>>(),
57+
);
58+
for vertex in code {
59+
let child = queue.pop().unwrap();
60+
add_edge(&mut result, child, *vertex);
61+
let cnt = list_count.get_mut(vertex).unwrap();
62+
*cnt -= 1;
63+
if *cnt == 0 {
64+
queue.push(*vertex);
65+
}
66+
}
67+
let u = queue.pop().unwrap();
68+
let v = queue.pop().unwrap();
69+
add_edge(&mut result, u, v);
70+
result
71+
}
72+
73+
#[cfg(test)]
74+
mod tests {
75+
use super::{add_edge, prufer_decode, prufer_encode, Graph};
76+
77+
fn equal_graphs<V: Ord + Copy>(g1: &mut Graph<V>, g2: &mut Graph<V>) -> bool {
78+
for adj in g1.values_mut() {
79+
adj.sort();
80+
}
81+
for adj in g2.values_mut() {
82+
adj.sort();
83+
}
84+
return g1 == g2;
85+
}
86+
87+
#[test]
88+
fn small_trees() {
89+
let mut g: Graph<u32> = Graph::new();
90+
// Binary tree with 7 vertices
91+
let edges = vec![(1, 2), (1, 3), (2, 4), (2, 5), (3, 6), (3, 7)];
92+
for (u, v) in edges {
93+
add_edge(&mut g, u, v);
94+
}
95+
let code = prufer_encode(&g);
96+
let vertices = g.keys().cloned().collect::<Vec<u32>>();
97+
let mut decoded = prufer_decode(&code, &vertices);
98+
assert_eq!(code, vec![3, 3, 2, 2, 1]);
99+
assert!(equal_graphs(&mut g, &mut decoded));
100+
101+
g.clear();
102+
// A path of length 10
103+
for v in 2..=9 {
104+
g.insert(v, vec![v - 1, v + 1]);
105+
}
106+
g.insert(1, vec![2]);
107+
g.insert(10, vec![9]);
108+
let code = prufer_encode(&g);
109+
let vertices = g.keys().cloned().collect::<Vec<u32>>();
110+
let mut decoded = prufer_decode(&code, &vertices);
111+
assert_eq!(code, vec![9, 8, 7, 6, 5, 4, 3, 2]);
112+
assert!(equal_graphs(&mut g, &mut decoded));
113+
114+
g.clear();
115+
// 7-5-3-1-2-4-6
116+
let edges = vec![(1, 2), (2, 4), (4, 6), (1, 3), (3, 5), (5, 7)];
117+
for (u, v) in edges {
118+
add_edge(&mut g, u, v);
119+
}
120+
let code = prufer_encode(&g);
121+
let vertices = g.keys().cloned().collect::<Vec<u32>>();
122+
let mut decoded = prufer_decode(&code, &vertices);
123+
assert_eq!(code, vec![5, 4, 3, 2, 1]);
124+
assert!(equal_graphs(&mut g, &mut decoded));
125+
}
126+
}

‎src/sorting/shell_sort.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
pub fn shell_sort<T: Ord + Copy>(values: &mut Vec<T>) {
1+
pub fn shell_sort<T: Ord + Copy>(values: &mut [T]) {
22
// shell sort works by swiping the value at a given gap and decreasing the gap to 1
3-
fn insertion<T: Ord + Copy>(values: &mut Vec<T>, start: usize, gap: usize) {
3+
fn insertion<T: Ord + Copy>(values: &mut [T], start: usize, gap: usize) {
44
for i in ((start + gap)..values.len()).step_by(gap) {
55
let val_current = values[i];
66
let mut pos = i;

0 commit comments

Comments
 (0)
Please sign in to comment.