├── .gitignore ├── .travis.yml ├── Cargo.toml ├── README.md └── src ├── data_structures ├── binary_heap.rs ├── binary_tree.rs ├── disjoint_set │ ├── mod.rs │ ├── quick_find.rs │ ├── quick_union.rs │ └── weighted_quick_union.rs ├── kd_tree.rs ├── mod.rs ├── priority_queue.rs └── stack.rs ├── lib.rs ├── main.rs ├── sorting ├── heapsort.rs ├── insertion_sort.rs ├── mergesort.rs ├── mod.rs ├── quicksort.rs ├── selection_sort.rs └── shellsort.rs └── utils └── mod.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | 3 | name = "rawgorithms" 4 | version = "0.0.1" 5 | authors = ["Thiago Pontes "] 6 | 7 | [dependencies] 8 | rand = "*" 9 | 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rawgorithms 2 | [![Build Status](https://travis-ci.org/thiagopnts/rawgorithms.png?branch=master)](https://travis-ci.org/thiagopnts/rawgorithms) 3 | 4 | #### Data Structures 5 | 6 | - Stack 7 | - Binary Heap 8 | - Priority Queue 9 | - Disjoint-set 10 | 11 | #### Sorting 12 | 13 | - Mergesort 14 | - Quicksort 15 | - Insertion Sort 16 | - Selection Sort 17 | - Shellsort 18 | - Heapsort 19 | 20 | 21 | #### Utils 22 | 23 | - Knuth Shuffle 24 | - Is Sorted 25 | -------------------------------------------------------------------------------- /src/data_structures/binary_heap.rs: -------------------------------------------------------------------------------- 1 | use std::vec::Vec; 2 | use utils::exch; 3 | 4 | pub struct BinaryHeap where T: PartialOrd + Clone { 5 | pq: Vec, 6 | n: usize 7 | } 8 | 9 | impl BinaryHeap where T: PartialOrd + Clone { 10 | pub fn new() -> BinaryHeap { 11 | BinaryHeap { pq: Vec::new(), n: 0 } 12 | } 13 | 14 | pub fn is_empty(&self) -> bool { 15 | self.n == 0 16 | } 17 | 18 | pub fn insert(&mut self, value: T) { 19 | if self.is_empty() { 20 | self.pq.push(value.clone()); 21 | } 22 | self.pq.push(value); 23 | self.n += 1; 24 | let n = self.n; 25 | self.swim(n); 26 | } 27 | 28 | pub fn delete_max(&mut self) -> Option { 29 | if self.is_empty() { 30 | return None; 31 | } 32 | let max = self.pq.remove(1); 33 | self.n -= 1; 34 | self.sink(1); 35 | Some(max) 36 | } 37 | 38 | fn swim(&mut self, n: usize) { 39 | let mut k = n; 40 | while k > 1 && self.pq[k / 2] < self.pq[k] { 41 | exch(&mut self.pq, k, k / 2); 42 | k = k / 2; 43 | } 44 | } 45 | 46 | fn sink(&mut self, k: usize) { 47 | let mut i = k; 48 | while (2 * i) <= self.n { 49 | let mut j = 2 * i; 50 | if j < self.n && self.pq[j] < self.pq[j + 1] { 51 | j += 1 52 | } 53 | if !(self.pq[i] < self.pq[j]) { 54 | break; 55 | } 56 | exch(&mut self.pq, i, j); 57 | i = j 58 | } 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /src/data_structures/binary_tree.rs: -------------------------------------------------------------------------------- 1 | 2 | type TreeNode = Option>; 3 | 4 | struct Node { 5 | pub left: TreeNode, 6 | pub right: TreeNode, 7 | pub value: i32, 8 | } 9 | 10 | 11 | impl Node { 12 | pub fn new(value: i32) -> Self { 13 | Node { 14 | left: None, 15 | right: None, 16 | value: value, 17 | } 18 | } 19 | 20 | pub fn insert(&mut self, value: i32) { 21 | if self.value < value { 22 | if let Some(ref mut right) = self.right { 23 | right.insert(value); 24 | } else { 25 | self.right = Some(Box::new(Node::new(value))); 26 | } 27 | } else { 28 | if let Some(ref mut left) = self.left { 29 | left.insert(value); 30 | } else { 31 | self.left = Some(Box::new(Node::new(value))); 32 | } 33 | } 34 | } 35 | 36 | pub fn pos_order(&self) { 37 | if let Some(ref left) = self.left { 38 | left.pos_order(); 39 | } 40 | if let Some(ref right) = self.right { 41 | right.pos_order(); 42 | } 43 | println!("{}", self.value); 44 | } 45 | 46 | pub fn pre_order(&self) { 47 | println!("{}", self.value); 48 | 49 | if let Some(ref left) = self.left { 50 | left.pre_order(); 51 | } 52 | if let Some(ref right) = self.right { 53 | right.pre_order(); 54 | } 55 | } 56 | 57 | pub fn in_order(&self) { 58 | if let Some(ref left) = self.left { 59 | left.in_order(); 60 | } 61 | println!("{}", self.value); 62 | if let Some(ref right) = self.right { 63 | right.in_order(); 64 | } 65 | } 66 | } 67 | 68 | pub type BinaryTree = Node; 69 | 70 | #[test] 71 | fn test_insert() { 72 | let mut root = BinaryTree::new(3); 73 | root.insert(2); 74 | root.insert(4); 75 | root.insert(5); 76 | root.insert(6); 77 | root.insert(1); 78 | if let Some(ref left) = root.left { 79 | assert_eq!(left.value, 2); 80 | } 81 | 82 | if let Some(ref right) = root.right { 83 | assert_eq!(right.value, 4); 84 | if let Some(ref right) = right.right { 85 | assert_eq!(right.value, 5); 86 | } 87 | } 88 | 89 | println!("In Order traversal"); 90 | root.in_order(); 91 | println!("\n"); 92 | println!("Pos Order traversal"); 93 | root.pos_order(); 94 | println!("Pre Order traversal"); 95 | root.pre_order(); 96 | } 97 | 98 | -------------------------------------------------------------------------------- /src/data_structures/disjoint_set/mod.rs: -------------------------------------------------------------------------------- 1 | pub use self::quick_find::QuickFind; 2 | pub use self::quick_union::QuickUnion; 3 | pub use self::weighted_quick_union::WeightedQuickUnion; 4 | 5 | mod quick_find; 6 | mod quick_union; 7 | mod weighted_quick_union; 8 | 9 | -------------------------------------------------------------------------------- /src/data_structures/disjoint_set/quick_find.rs: -------------------------------------------------------------------------------- 1 | 2 | use std::vec::Vec; 3 | 4 | pub struct QuickFind { 5 | id: Vec 6 | } 7 | 8 | impl QuickFind { 9 | pub fn new(n: usize) -> QuickFind { 10 | QuickFind{ id: (0 .. n).map(|i| i).collect() } 11 | } 12 | 13 | pub fn connected(&self, p: usize, q: usize) -> bool { 14 | self.id[p] == self.id[q] 15 | } 16 | 17 | pub fn union(&mut self, p: usize, q: usize) { 18 | let pid = self.id[p]; 19 | let qid = self.id[q]; 20 | for i in 0..self.id.len() { 21 | if self.id[i] == pid { 22 | self.id[i] = qid; 23 | } 24 | } 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /src/data_structures/disjoint_set/quick_union.rs: -------------------------------------------------------------------------------- 1 | use std::vec::Vec; 2 | 3 | pub struct QuickUnion { 4 | id: Vec 5 | } 6 | 7 | impl QuickUnion { 8 | pub fn new(n: usize) -> QuickUnion { 9 | QuickUnion{ id: (0 .. n).map(|i| i).collect() } 10 | } 11 | 12 | fn root(&self, i: usize) -> usize { 13 | if i == self.id[i] { 14 | return i; 15 | } 16 | self.root(self.id[i]) 17 | } 18 | 19 | pub fn connected(&self, p: usize, q: usize) -> bool { 20 | self.root(p) == self.root(q) 21 | } 22 | 23 | pub fn union(&mut self, p: usize, q: usize) { 24 | let i = self.root(p); 25 | let j = self.root(q); 26 | self.id.remove(i); 27 | self.id.insert(i, j); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/data_structures/disjoint_set/weighted_quick_union.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | 3 | use std::vec::Vec; 4 | 5 | pub struct WeightedQuickUnion { 6 | id: Vec, 7 | size: Vec 8 | } 9 | 10 | impl WeightedQuickUnion { 11 | pub fn new(n: usize) -> WeightedQuickUnion { 12 | WeightedQuickUnion { id: (0 .. n).map(|i| i).collect(), size: (0 .. n).map(|_| 1).collect() } 13 | } 14 | 15 | fn root(&self, i: usize) -> usize { 16 | if i == self.id[i] { 17 | return i; 18 | } 19 | self.root(self.id[i]) 20 | } 21 | 22 | pub fn connected(&self, p: usize, q: usize) -> bool { 23 | self.root(p) == self.root(q) 24 | } 25 | 26 | pub fn union(&mut self, p: usize, q: usize) { 27 | let i = self.root(p); 28 | let j = self.root(q); 29 | let current_i = self.size[i]; 30 | let current_j = self.size[j]; 31 | if i == j { return; } 32 | if self.size[i] < self.size[j] { 33 | // FIXME 34 | self.id.remove(i); 35 | self.id.insert(i, j); 36 | self.size.remove(j); 37 | self.size.insert(j, current_j + current_i); 38 | } else { 39 | self.id.remove(j); 40 | self.id.insert(j, i); 41 | self.size.remove(i); 42 | self.size.insert(i, current_j + current_i); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/data_structures/kd_tree.rs: -------------------------------------------------------------------------------- 1 | 2 | 3 | type Color = Typle3; 4 | 5 | struct Node { 6 | left: Option>>, 7 | right: Option>>, 8 | data: T 9 | } 10 | 11 | impl Node { 12 | fn new(data: T) -> Node { 13 | Node { data: data, left: None, right: None } 14 | } 15 | } 16 | 17 | pub struct KDTree { 18 | current_i: usize, 19 | dimensions: usize, 20 | root: Option>> 21 | } 22 | 23 | impl KDTree { 24 | pub fn new(dimensions: usize) -> KDTree { 25 | KDTree { current_i: 0, dimensions: dimensions, root: None } 26 | } 27 | 28 | pub fn insert(&mut self, data: T) { 29 | self.current_i = 0; 30 | match self.root.take() { 31 | None => self.root = Node::new(data), 32 | Some(mut root) => self.insert_node(root, data) 33 | } 34 | } 35 | 36 | fn insert_node(&mut self, node: Box>, data: T) { 37 | } 38 | 39 | fn index(&mut self) -> usize { 40 | self.current_i % self.dimensions 41 | } 42 | } 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/data_structures/mod.rs: -------------------------------------------------------------------------------- 1 | pub use self::stack::Stack; 2 | pub use self::binary_heap::BinaryHeap; 3 | pub use self::priority_queue::PriorityQueue; 4 | pub use self::disjoint_set::QuickUnion; 5 | pub use self::disjoint_set::WeightedQuickUnion; 6 | pub use self::disjoint_set::QuickFind; 7 | 8 | mod stack; 9 | mod binary_heap; 10 | mod priority_queue; 11 | mod disjoint_set; 12 | -------------------------------------------------------------------------------- /src/data_structures/priority_queue.rs: -------------------------------------------------------------------------------- 1 | 2 | use std::vec::Vec; 3 | 4 | pub struct PriorityQueue where T: PartialOrd + Clone { 5 | pq: Vec 6 | } 7 | 8 | // This is a simple priority queue implementation with 9 | // O(1) insertion and O(n) max/min deletion. For a O(log n) insertion/max/min deletion 10 | // check Binary Heap data structure. 11 | impl PriorityQueue where T: PartialOrd + Clone { 12 | pub fn new() -> PriorityQueue { 13 | PriorityQueue { pq: Vec::new() } 14 | } 15 | 16 | pub fn len(&self) -> usize { 17 | self.pq.len() 18 | } 19 | 20 | pub fn is_empty(&self) -> bool { 21 | self.pq.len() == 0 22 | } 23 | 24 | pub fn insert(&mut self, value: T) { 25 | self.pq.push(value); 26 | } 27 | 28 | pub fn max(&mut self) -> Option { 29 | if self.is_empty() { return None } 30 | let max = self.max_index(); 31 | Some(self.pq[max].clone()) 32 | } 33 | 34 | pub fn min(&mut self) -> Option { 35 | if self.is_empty() { return None } 36 | let min = self.min_index(); 37 | Some(self.pq[min].clone()) 38 | } 39 | 40 | pub fn delete_max(&mut self) -> Option { 41 | if self.is_empty() { return None; } 42 | let max = self.max_index(); 43 | Some(self.pq.remove(max).clone()) 44 | } 45 | 46 | pub fn delete_min(&mut self) -> Option { 47 | if self.is_empty() { return None; } 48 | let min = self.min_index(); 49 | Some(self.pq.remove(min).clone()) 50 | } 51 | 52 | fn max_index(&self) -> usize { 53 | let mut max = 0; 54 | for i in 1..self.pq.len() - 1 { 55 | if self.pq[max] < self.pq[i] { 56 | max = i; 57 | } 58 | } 59 | max 60 | } 61 | 62 | fn min_index(&self) -> usize { 63 | let mut min = 0; 64 | for i in 0..self.pq.len() - 1 { 65 | if self.pq[i] < self.pq[i + 1] { 66 | min = i; 67 | } 68 | } 69 | min 70 | } 71 | } 72 | 73 | #[cfg(test)] 74 | mod test { 75 | use super::PriorityQueue; 76 | 77 | #[test] 78 | fn test_keep_min() { 79 | let mut pq = PriorityQueue::new(); 80 | pq.insert(3); 81 | pq.insert(2); 82 | pq.insert(1); 83 | pq.insert(4); 84 | assert!(pq.min().unwrap() == 1); 85 | } 86 | 87 | #[test] 88 | fn test_keep_max() { 89 | let mut pq = PriorityQueue::new(); 90 | pq.insert(2); 91 | pq.insert(4); 92 | pq.insert(1); 93 | pq.insert(3); 94 | assert!(pq.max().unwrap() == 4); 95 | } 96 | 97 | #[test] 98 | fn test_is_empty() { 99 | let mut pq = PriorityQueue::new(); 100 | assert!(pq.is_empty()); 101 | pq.insert(1); 102 | assert!(!pq.is_empty()); 103 | } 104 | 105 | #[test] 106 | fn test_len() { 107 | let mut pq = PriorityQueue::new(); 108 | assert!(pq.len() == 0); 109 | pq.insert(2); 110 | pq.insert(4); 111 | pq.insert(1); 112 | assert!(pq.len() == 3); 113 | } 114 | 115 | #[test] 116 | fn test_delete_min() { 117 | let mut pq = PriorityQueue::new(); 118 | pq.insert(3); 119 | pq.insert(2); 120 | pq.insert(1); 121 | pq.insert(4); 122 | assert!(pq.len() == 4); 123 | assert!(pq.delete_min().unwrap() == 1); 124 | assert!(pq.len() == 3); 125 | } 126 | 127 | #[test] 128 | fn test_delete_max() { 129 | let mut pq = PriorityQueue::new(); 130 | pq.insert(2); 131 | pq.insert(10); 132 | pq.insert(1); 133 | pq.insert(6); 134 | pq.insert(3); 135 | assert!(pq.len() == 5); 136 | assert!(pq.delete_max().unwrap() == 10); 137 | assert!(pq.len() == 4); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/data_structures/stack.rs: -------------------------------------------------------------------------------- 1 | #[derive(Clone)] 2 | struct Node { 3 | data: T, 4 | next: Option>> 5 | } 6 | 7 | impl Node { 8 | fn new(value: T) -> Node { 9 | Node{data: value, next: None} 10 | } 11 | } 12 | 13 | pub struct Stack { 14 | length: usize, 15 | first: Option>> 16 | } 17 | 18 | impl Stack { 19 | pub fn new() -> Stack { 20 | Stack{length: 0, first: None} 21 | } 22 | 23 | pub fn push(&mut self, value: T) { 24 | self.length += 1; 25 | self.first = Some(Box::new(Node { 26 | data: value, 27 | next: self.first.take() 28 | })); 29 | } 30 | 31 | pub fn peek(&mut self) -> Option<&T> { 32 | match self.first { 33 | None => None, 34 | Some(ref head) => Some(&head.data) 35 | } 36 | } 37 | 38 | pub fn pop(&mut self) -> Option { 39 | match self.first.take() { 40 | None => None, 41 | Some(mut head) => { 42 | self.first = head.next.take(); 43 | self.length -= 1; 44 | Some(head.data) 45 | } 46 | } 47 | } 48 | 49 | pub fn len(&self) -> usize { 50 | self.length 51 | } 52 | } 53 | 54 | #[cfg(test)] 55 | mod test { 56 | use super::Stack; 57 | 58 | #[test] 59 | fn test_push() { 60 | let mut stack = Stack::new(); 61 | stack.push(1); 62 | stack.push(2); 63 | stack.push(3); 64 | assert_eq!(3, stack.len()); 65 | } 66 | 67 | #[test] 68 | fn test_pop() { 69 | let mut stack = Stack::new(); 70 | stack.push(1); 71 | stack.push(2); 72 | stack.push(3); 73 | assert_eq!(3, stack.len()); 74 | 75 | let last = stack.pop().unwrap(); 76 | assert_eq!(3, last); 77 | assert_eq!(2, stack.len()); 78 | 79 | let last = stack.pop().unwrap(); 80 | assert_eq!(2, last); 81 | 82 | assert_eq!(1, stack.len()); 83 | } 84 | 85 | #[test] 86 | fn test_peek() { 87 | let mut stack = Stack::new(); 88 | stack.push(3); 89 | stack.push(10); 90 | stack.push(1); 91 | assert_eq!(*stack.peek().unwrap(), 1); 92 | assert_eq!(stack.len(), 3); 93 | } 94 | 95 | #[test] 96 | fn test_pop_empty_stack() { 97 | let mut stack: Stack = Stack::new(); 98 | assert_eq!(stack.pop(), None); 99 | } 100 | } 101 | 102 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | 3 | extern crate rand; 4 | 5 | pub mod sorting; 6 | pub mod utils; 7 | pub mod data_structures; 8 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | mod sorting; 3 | mod data_structures; 4 | mod utils; 5 | 6 | 7 | fn main() { 8 | let mut a = utils::knuth_shuffle(10); 9 | sorting::heapsort(&mut a); 10 | println!("{:?}", a); 11 | } 12 | -------------------------------------------------------------------------------- /src/sorting/heapsort.rs: -------------------------------------------------------------------------------- 1 | use utils::exch; 2 | // heapsort works for one-based indexed arrays so it will ignore the first element of the 3 | // given array 4 | pub fn heapsort(array: &mut Vec) where T: Clone + PartialOrd { 5 | let mut len = array.len() - 1; 6 | let mut k = len / 2; 7 | while k >= 1 { 8 | sink(array, k, len); 9 | k -= 1 10 | } 11 | 12 | while len > 1 { 13 | exch(array, 1, len); 14 | len -= 1; 15 | sink(array, 1, len); 16 | } 17 | } 18 | 19 | fn sink(array: &mut Vec, k: usize, n: usize) where T: Clone + PartialOrd { 20 | let mut i = k; 21 | while (2 * i) <= n { 22 | let mut j = 2 * i; 23 | if j < n && array[j] < array[j + 1] { 24 | j += 1 25 | } 26 | if !(array[i] < array[j]) { 27 | break; 28 | } 29 | exch(array, i, j); 30 | i = j 31 | } 32 | } 33 | 34 | #[cfg(test)] 35 | mod test { 36 | use super::heapsort; 37 | 38 | #[test] 39 | fn test_heapsort() { 40 | // heapsort works only for 1 index-based arrays, so it will ignore the first element 41 | let mut shuffled_array = vec![1, 2, 1, 3, 5, 4, 6, 8, 9, 7]; 42 | 43 | heapsort(&mut shuffled_array); 44 | 45 | for value in 1..10 { 46 | assert!(value == shuffled_array[value]); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/sorting/insertion_sort.rs: -------------------------------------------------------------------------------- 1 | use utils::exch; 2 | 3 | pub fn insertion_sort(a: &mut Vec) { 4 | let len = a.len(); 5 | 6 | for i in 0..len { 7 | for j in (1..i + 1).rev() { 8 | if a.get(j) < a.get(j - 1) { 9 | exch(a, j, j - 1); 10 | } else { 11 | break; 12 | } 13 | } 14 | } 15 | } 16 | 17 | #[cfg(test)] 18 | mod test { 19 | use super::insertion_sort; 20 | use utils::knuth_shuffle; 21 | 22 | #[test] 23 | fn test_insertion_sort() { 24 | let mut shuffled_array = knuth_shuffle(100); 25 | insertion_sort(&mut shuffled_array); 26 | 27 | for value in 1..100 { 28 | assert!(value == shuffled_array[value - 1]); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/sorting/mergesort.rs: -------------------------------------------------------------------------------- 1 | // in-place merge sort implementation 2 | pub fn mergesort(a: &mut Vec) { 3 | let mut aux = a.clone(); 4 | let len = a.len() - 1; 5 | sort(a, &mut aux, 0, len); 6 | } 7 | 8 | fn sort(a: &mut Vec, aux: &mut Vec, lo: usize, hi: usize) { 9 | if hi <= lo { return; } 10 | let mid = lo + (hi - lo) / 2; 11 | sort(a, aux, lo, mid); 12 | sort(a, aux, mid + 1, hi); 13 | merge(a, aux, lo, mid, hi); 14 | } 15 | 16 | fn merge(a: &mut Vec, aux: &mut Vec, lo: usize, mid: usize, hi: usize) { 17 | for k in lo..hi + 1 { 18 | aux[k] = a[k].clone(); 19 | } 20 | 21 | let mut i = lo; 22 | let mut j = mid + 1; 23 | 24 | for k in lo..hi + 1 { 25 | if i > mid { 26 | a[k] = aux[j].clone(); 27 | j += 1 28 | } else if j > hi { 29 | a[k] = aux[i].clone(); 30 | i += 1 31 | } else if aux[j] < aux[i] { 32 | a[k] = aux[j].clone(); 33 | j += 1 34 | } else { 35 | a[k] = aux[i].clone(); 36 | i += 1 37 | } 38 | } 39 | } 40 | 41 | #[cfg(test)] 42 | mod test { 43 | use super::mergesort; 44 | use utils::knuth_shuffle; 45 | 46 | #[test] 47 | fn test_mergesort() { 48 | let mut shuffled_array = knuth_shuffle(100); 49 | mergesort(&mut shuffled_array); 50 | 51 | for value in 1..100 { 52 | assert!(value == shuffled_array[value - 1]); 53 | } 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /src/sorting/mod.rs: -------------------------------------------------------------------------------- 1 | pub use self::mergesort::mergesort; 2 | pub use self::quicksort::quicksort; 3 | pub use self::selection_sort::selection_sort; 4 | pub use self::insertion_sort::insertion_sort; 5 | pub use self::shellsort::shellsort; 6 | pub use self::heapsort::heapsort; 7 | 8 | mod mergesort; 9 | mod quicksort; 10 | mod selection_sort; 11 | mod insertion_sort; 12 | mod shellsort; 13 | mod heapsort; 14 | -------------------------------------------------------------------------------- /src/sorting/quicksort.rs: -------------------------------------------------------------------------------- 1 | use utils::{exch,shuffle}; 2 | 3 | pub fn quicksort(a: &mut Vec) { 4 | shuffle(a); 5 | let len = a.len() - 1; 6 | sort(a, 0, len as i64); 7 | } 8 | 9 | fn sort(a: &mut Vec, lo: i64, hi: i64) { 10 | if hi <= lo { return; } 11 | let j = partition(a, lo, hi); 12 | sort(a, lo, j - 1); 13 | sort(a, j + 1, hi); 14 | } 15 | 16 | fn partition(a: &mut Vec, lo: i64, hi: i64) -> i64 { 17 | let mut i = lo as usize; 18 | let mut j = hi as usize; 19 | loop { 20 | while a[i] < a[lo as usize] { 21 | i += 1; 22 | if i == hi as usize { break; } 23 | } 24 | 25 | while a[lo as usize] < a[j] { 26 | j -= 1; 27 | if j == lo as usize { break; } 28 | } 29 | 30 | if i >= j { break; } 31 | exch(a, i, j); 32 | } 33 | 34 | exch(a, lo as usize, j); 35 | j as i64 36 | } 37 | 38 | #[cfg(test)] 39 | mod test { 40 | use super::quicksort; 41 | use utils::knuth_shuffle; 42 | 43 | #[test] 44 | fn test_quicksort() { 45 | let mut shuffled_array = knuth_shuffle(100); 46 | quicksort(&mut shuffled_array); 47 | 48 | for value in 1..100 { 49 | assert_eq!(value, shuffled_array[value - 1]); 50 | } 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /src/sorting/selection_sort.rs: -------------------------------------------------------------------------------- 1 | use utils::exch; 2 | 3 | pub fn selection_sort(a: &mut Vec) { 4 | let mut min; 5 | let len = a.len(); 6 | for i in 0..len { 7 | min = i; 8 | for j in i + 1..len { 9 | if a[j] < a[min] { 10 | min = j; 11 | } 12 | } 13 | exch(a, i, min); 14 | } 15 | } 16 | 17 | #[cfg(test)] 18 | mod test { 19 | use super::selection_sort; 20 | use utils::knuth_shuffle; 21 | 22 | #[test] 23 | fn test_selection_sort() { 24 | let mut shuffled_array = knuth_shuffle(100); 25 | selection_sort(&mut shuffled_array); 26 | 27 | for value in 1..100 { 28 | assert_eq!(value, shuffled_array[value - 1]); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/sorting/shellsort.rs: -------------------------------------------------------------------------------- 1 | use utils::exch; 2 | 3 | pub fn shellsort(a: &mut Vec) { 4 | let len = a.len() as i64; 5 | let mut h = 1i64; 6 | while h < (len / 3) { 7 | h = 3 * h + 1; 8 | } 9 | 10 | while h >= 1 { 11 | for i in h..len { 12 | let mut j: i64 = i; 13 | while j >= h && a[j as usize] < a[(j - h) as usize] { 14 | exch(a, j as usize, (j - h) as usize); 15 | j -= h; 16 | } 17 | } 18 | h = h / 3; 19 | } 20 | } 21 | 22 | #[cfg(test)] 23 | mod test { 24 | use super::shellsort; 25 | use utils::knuth_shuffle; 26 | 27 | #[test] 28 | fn test_shellsort() { 29 | let mut shuffled_array = knuth_shuffle(100); 30 | shellsort(&mut shuffled_array); 31 | 32 | for value in 1..100 { 33 | assert_eq!(value, shuffled_array[value - 1]); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | extern crate rand; 2 | 3 | use std::vec::Vec; 4 | 5 | use self::rand::random; 6 | 7 | // linear time shuffling algorithm 8 | pub fn knuth_shuffle(n: usize) -> Vec { 9 | let mut vec: Vec = (0 .. n).map(|i| i + 1).collect(); 10 | for i in 0..n { 11 | let r = random::() % (i + 1); 12 | let value: usize = vec[i]; 13 | vec[i] = vec[r]; 14 | vec[r] = value; 15 | } 16 | vec 17 | } 18 | 19 | pub fn shuffle(v: &mut Vec) where T: Clone, T: PartialOrd { 20 | for i in 0usize..v.len() { 21 | let r = random::() % (i + 1); 22 | exch(v, i, r); 23 | } 24 | } 25 | 26 | pub fn exch(a: &mut Vec, i: usize, j: usize) { 27 | let from = a[i].clone(); 28 | let to = a[j].clone(); 29 | a[i] = to; 30 | a[j] = from; 31 | } 32 | 33 | pub fn is_sorted(a: &Vec) -> bool { 34 | for i in 1..a.len() { 35 | if a[i - 1] > a[i] { return false; } 36 | } 37 | true 38 | } 39 | 40 | 41 | --------------------------------------------------------------------------------