diff --git a/Cargo.toml b/Cargo.toml index f77c061..f7318ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,11 @@ [package] name = "algori" -version = "0.11.5" + +version = "0.11.10" edition = "2021" authors = ["Donjuan Platinum "] -license = "MIT" -description = "some common rust_algorithms, Everyone can participate, and the project will continue to be updated, all the algorithms comes from " +license = "GPL-2.0-only" +description = "Rust Algorithms" repository = "https://github.com/donjuanplatinum/Algori" readme = "README.md" documentation = "https://docs.rs/algori" diff --git a/README.md b/README.md index ad2c161..53e839c 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,32 @@ -# Algorithms_Rust -[![crates.io](https://img.shields.io/crates/dr/algori)](https://crates.io/crates/algori) -[![Coverage Status](https://coveralls.io/repos/github/donjuanplatinum/Algori/badge.svg?branch=main)](https://coveralls.io/github/donjuanplatinum/Algori?branch=main) -[![Version](https://img.shields.io/crates/v/algori)](https://crates.io/crates/algori) -[![Chinese](./README.zh.md)](./README.zh.md) -[![English](./README.md)](./README.md) +
-Algorithm_rust是一个rust的算法库 +[![](https://img.shields.io/crates/d/algori.svg)](https://crates.io/crates/algori) +[![](https://img.shields.io/github/forks/barrensea/algori.svg)](https://github.com/BarrenSea/algori/fork) +[![](https://img.shields.io/github/repo-size/barrensea/algori.svg)](https://github.com/BarrenSea/algori) +[![](https://img.shields.io/github/stars/barrensea/algori.svg)](https://github.com/BarrenSea/algori) +[![](https://img.shields.io/github/commit-activity/t/barrensea/algori.svg)](https://github.com/BarrenSea/algori) -## 算法 -### 排序 -1. 二分插入排序 -2. 泡泡排序 -3. 计数排序 -4. 堆排序 -5. 插入排序 -6. 分治排序 -7. 快速排序 -8. 基数排序 -9. 选择排序 -10. pdq排序 -### 矩阵操作 -1. 方阵相加 -2. 方阵乘法 -3. 矩阵结构 -### 查找 -1. 二分查找 -2. 线性查找 +
-### 数据结构 -1. 最大优先队列 -2. 栈 -3. 链表 -### 子数组 -1. 分治最大子数组 -2. 线性最大子数组 -### 数学算法与变换 -1. 离散傅立叶变换 -## 欢迎拉取请求 +

+ + + +

Algori

+

+ Rust Algorithms +
+
+ Docs + · + Matrix +

+

+ +## Algorithms +### Sorting +- [Insertionsort](./doc/sorting/README.md) +### Structures +- [Heap](./doc/structure/README.md) diff --git a/doc/sorting/README.md b/doc/sorting/README.md new file mode 100644 index 0000000..970617e --- /dev/null +++ b/doc/sorting/README.md @@ -0,0 +1,10 @@ +# Sorting 排序 + ++ 插入排序 + +## 插入排序 +[![Insertion_sort](./insertion_sort.svg)](./insertion_sort.svg) + +### 复杂度 +最优时间复杂度: O(n) +最坏时间复杂度: O(n ^ 2) diff --git a/doc/sorting/insertion_sort.svg b/doc/sorting/insertion_sort.svg new file mode 100644 index 0000000..f7511a9 --- /dev/null +++ b/doc/sorting/insertion_sort.svg @@ -0,0 +1 @@ +
A
A
A
A
A
A
2
2
2
2
2
2
3
3
3
3
3
3
4
4
4
4
4
4
5
5
5
5
5
5
6
6
6
6
6
6
7
7
7
7
7
7
8
8
8
8
8
8
9
9
9
9
9
9
10
10
10
10
10
10
8
8
8
8
8
8
2
2
2
2
2
2
6
6
6
6
6
6
3
3
3
3
3
3
10
10
10
10
10
10
9
9
9
9
9
9
4
4
4
4
4
4
A
A
A
7
7
7
7
7
7
5
5
5
\ No newline at end of file diff --git a/doc/structure/README.md b/doc/structure/README.md new file mode 100644 index 0000000..e543ae2 --- /dev/null +++ b/doc/structure/README.md @@ -0,0 +1,7 @@ +# Structure 数据结构 + ++ Heap/Priority Queue 堆/优先队列 + +## Heap/Priority Queue 堆/优先队列 +[![Heap](./binary_heap_insert.svg)](./binary_heap_insert.svg) + diff --git a/doc/structure/binary_heap_insert.svg b/doc/structure/binary_heap_insert.svg new file mode 100644 index 0000000..18ba068 --- /dev/null +++ b/doc/structure/binary_heap_insert.svg @@ -0,0 +1 @@ +
17
14
12
11
13
8
3
6
7
2
9
15
15
10
10
16
\ No newline at end of file diff --git a/imgs/algori.png b/imgs/algori.png new file mode 100644 index 0000000..6d00d20 Binary files /dev/null and b/imgs/algori.png differ diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..4c3c946 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,13 @@ +// Copyright 2024 Barrensea. Licensed under GPL-2 + +//! Algori - Rust Algorithms +//! + +/// Sortion Algorithms +pub mod sorting; + +/// Structures +pub mod structure; + + + diff --git a/src/sorting/insertion_sort.rs b/src/sorting/insertion_sort.rs new file mode 100644 index 0000000..90411b9 --- /dev/null +++ b/src/sorting/insertion_sort.rs @@ -0,0 +1,62 @@ +/// # Insertion_Sort +pub fn insertion_sort(array: &mut[T]) -> () +where T: PartialOrd, +{ + for point in 1..array.len() { + let mut current_point: usize = point; + while current_point > 0 && array[current_point] < array[current_point - 1] { + array.swap(current_point,current_point - 1); + current_point -= 1; + } + } +} + +/// # Reverse Insertion_Sort +pub fn reverse_insertion_sort(array: &mut[T]) -> () +where T: PartialOrd, +{ + for point in 1..array.len() { + let mut current_point: usize = point; + while current_point > 0 && array[current_point] > array[current_point - 1] { + array.swap(current_point,current_point - 1); + current_point -= 1; + } + } +} + +#[cfg(test)] +mod insertion_sort_tests { + use super::{insertion_sort,reverse_insertion_sort}; + use super::super::is_sorted; + #[test] + fn empty() -> () + { + let mut a: [i32;0] = []; + insertion_sort(&mut a); + + assert_eq!(is_sorted(&mut a,|a,b| a <= b),true); + } + + #[test] + fn one_element() -> () + { + let mut a: [i32;1] = [1]; + insertion_sort(&mut a); + assert_eq!(is_sorted(&mut a ,|a,b| a <= b),true); + } + #[test] + fn positive() -> () + { + let mut a = [1,123,123,12,4234,42,1123,123,15112,312]; + insertion_sort(&mut a); + assert_eq!(is_sorted(&mut a,|a,b| a <= b),true); + } + #[test] + fn reverse() -> () + { + let mut a = [1,123,123,12,4234,42,1123,123,15112,312]; + reverse_insertion_sort(&mut a); + assert_eq!(is_sorted(&mut a,|a,b| a >= b),true); + } +} + diff --git a/src/sorting/mod.rs b/src/sorting/mod.rs new file mode 100644 index 0000000..cab274e --- /dev/null +++ b/src/sorting/mod.rs @@ -0,0 +1,5 @@ +mod utils; +mod insertion_sort; + +pub use self::utils::*; +pub use self::insertion_sort::* ; diff --git a/src/sorting/utils.rs b/src/sorting/utils.rs new file mode 100644 index 0000000..b2b7ac0 --- /dev/null +++ b/src/sorting/utils.rs @@ -0,0 +1,52 @@ +/// # Determine a slice if it is ordered +/// *Feature* : Use a Function to check if a slice is sorted or not +/// +/// *Return* : if is sorted or not sorted, return true , if the element cant compare, return false +/// +/// # Use +/// ``` +/// use algori::sorting::{is_sorted,insertion_sort}; +/// let mut a = [1,3,2,0,123,1,1,4634,341,2312452,351]; +/// assert_eq!(is_sorted(&mut a, |a,b|a <=b),false); +/// +/// insertion_sort(&mut a); +/// assert_eq!(is_sorted(&mut a,|a,b|a<=b),true); +/// ``` +pub fn is_sorted<'a, T>(array: &'a [T],compare: fn(&T,&T)->bool) -> bool +where T: PartialOrd + 'a, +{ + if array.len() == 0 {return true;} + for i in 0..array.len() - 1 { + match compare(&array[i],&array[i+1]) { + true => {continue;}, + false => {return false;}, + } + } + return true; +} + + +#[cfg(test)] +mod issorted_test { + use super::is_sorted; + #[test] + fn sorted() ->() { + let a = [1,2,3,4,5,6,111,321312321,623123124]; + assert_eq!(is_sorted(& a, |a,b| a<=b),true); + } + #[test] + fn unsorted() -> () { + let a = [2,0,3,0,4,9,323,1,4,7,1,233,6,7]; + assert_eq!(is_sorted(&a, |a,b| a <= b),false); + } + #[test] + fn char_compare() ->() { + let a: &[char] = &['a','b','c','d','e','f','g','h']; + assert_eq!(is_sorted(&a ,|a,b| a <= b),true); + } + #[test] + fn reverse() -> () { + let a = [7,6,5,4,3,2,1,0]; + assert_eq!(is_sorted(&a,|a,b| a >= b),true); + } +} diff --git a/src/structure/heap.rs b/src/structure/heap.rs new file mode 100644 index 0000000..3f52e3d --- /dev/null +++ b/src/structure/heap.rs @@ -0,0 +1,189 @@ +macro_rules! left_child { + ($parent:ident) => { + ($parent <<1) + 1 as usize + }; +} + + +macro_rules! right_child { + ($parent:ident) => { + ($parent <<1) + 2 as usize + }; +} + + +macro_rules! parent { + ($child:ident) => { + ($child - 1) >> 1 + }; +} + + + + +/// # Heap(Priority Queue) +/// Heap is a completely binary tree , Its parent node always maintains a relationship(define in comparator) with its child nodes +/// # Example +/// ``` +/// use algori::structure::Heap; +/// //Create a Max Priority(Max Heap) +/// let mut a: Heap = Heap::new(|a,b| a >= b); +/// a.push(1); a.push(100); a.push(40); a.push(0); +/// assert_eq!(a.pop().unwrap(),100); assert_eq!(a.pop().unwrap(),40); +/// ``` +#[derive(Debug,Clone)] +pub struct Heap { + items: Vec, + comparator: fn(&T,&T) -> bool, +} + +use core::ops::Index; +impl Index for Heap +{ + type Output = T; + fn index(&self,index: usize) -> &Self::Output { + return &self.items[index]; + } +} + +#[allow(dead_code)] +impl Heap { + /// Create A Heap With A Comparator + /// ``` + /// use algori::structure::Heap; + /// let a: Heap = Heap::new(|a,b| a >= b); + /// ``` + pub fn new(comparator: fn(&T,&T) -> bool) -> Self { + return Self { + items: vec!(), + comparator, + }; + } + /// Return The Length Of Heap + pub fn len(&self) -> usize { + return self.items.len(); + } + pub fn is_empty(&self) -> bool { + return self.items.is_empty(); + } + /// heapify_down use the comparator + fn heapify_down(&mut self,start: usize,end:usize) { + let mut better_element_index: usize = start; + if right_child!(start) < end && (self.comparator)(&self.items[right_child!(start)],&self.items[better_element_index]) { + better_element_index = right_child!(start); + } + if left_child!(start) < end && (self.comparator)(&self.items[left_child!(start)],&self.items[better_element_index]) { + better_element_index = left_child!(start); + } + if better_element_index != start { + self.items.swap(start,better_element_index); + self.heapify_down(better_element_index,end); + } + } + /// Push A New Element and heapify + pub fn push(&mut self,value: T) ->() + { + self.items.push(value); + let mut point: usize = self.len() - 1; + while point > 0 && (self.comparator)(&self.items[point],&self.items[parent!(point)]) { + self.items.swap(point,parent!(point)); + point = parent!(point); + } + } + /// Pop the Top Element + pub fn pop(&mut self) -> Result { + if self.is_empty() {return Err("Heap Is Empty!");} + if self.len() == 1 {return Ok(self.items.pop().unwrap());} + // pop the top element + let pop_element:T = self.items.swap_remove(0); + self.heapify_down(0,self.len()); + Ok(pop_element) + } + /// heap_sort use the comparator + pub fn sort(&mut self) -> () { + let len = self.len(); + // heap_sort + for i in (1..len).rev() { + self.items.swap(0, i); + self.heapify_down(0, i); + } + } + + /// clear all the elements + pub fn clear(&mut self) ->() { + self.items.clear(); + } +} + +#[allow(unused_parens)] +#[allow(dead_code)] +impl Heap { + pub fn comparator(&self) -> (fn(&T,&T) -> bool) + { + return self.comparator; + } +} + + + + +#[cfg(test)] +mod heap_tests { + use super::Heap; + #[test] + fn comparator_test() ->() { + let a: Heap = Heap::new(|a,b| a > b); + let c = (a.comparator())(&6,&7); + assert_eq!(c,false) + } + #[test] + fn macro_test() ->() { + let mut a = 0; + let l = left_child!(a); + let r = right_child!(a); + assert_eq!(l,1); + assert_eq!(r,2); + a = 20; + let p = parent!(a); + assert_eq!(9,p); + } + #[test] + fn max_heap_operation() -> () { + let mut a: Heap = Heap::new(|a,b| a >= b); + a.push(60); + a.push(2); + a.push(30); + a.push(100); + let mut vec: Vec = vec!(); + vec.push(100); + vec.push(60); + vec.push(30); + vec.push(2); + assert_eq!(a.items,vec); + } + #[test] + fn min_heap_operation() -> (){ + let mut a: Heap = Heap::new(|a,b| a <= b); + a.push(60); + a.push(2); + a.push(30); + a.push(100); + a.push(1); + a.push(40); + let mut vec: Vec = vec!(); + vec.push(1); + vec.push(2); + vec.push(30); + vec.push(100); + vec.push(60); + vec.push(40); + assert_eq!(a.items,vec); + } + #[test] + fn sort() -> () { + let mut a: Heap = Heap::new(|a,b| a>=b); + a.push(199); a.push(0); a.push(20); a.push(40); + a.sort(); + assert_eq!(a.items,[0,20,40,199]); + } +} diff --git a/src/structure/mod.rs b/src/structure/mod.rs new file mode 100644 index 0000000..b06d3c5 --- /dev/null +++ b/src/structure/mod.rs @@ -0,0 +1,5 @@ + +mod heap; + + +pub use self::heap::*;