diff --git a/src/lib.rs b/src/lib.rs index 910bf05de06129c3e6e5f6fd2354d02770e76cda..15e83cc446c7f9e450834f3855457c585d616316 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,16 +18,17 @@ pub mod number_theory; pub mod searching; pub mod sorting; pub mod string; +pub mod linked_list; #[cfg(test)] mod tests { + use super::sorting; #[test] fn quick_sort() { //descending let mut ve1 = vec![6, 5, 4, 3, 2, 1]; sorting::quick_sort(&mut ve1); - assert!(sorting::is_sorted(&ve1)); //pre-sorted diff --git a/src/linked_list/mod.rs b/src/linked_list/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..154739daa58daa893973847e0ddbbfb65f9fc5d7 --- /dev/null +++ b/src/linked_list/mod.rs @@ -0,0 +1 @@ +pub mod simple_linked_list; \ No newline at end of file diff --git a/src/linked_list/simple_linked_list.rs b/src/linked_list/simple_linked_list.rs new file mode 100644 index 0000000000000000000000000000000000000000..69d725a03e4a7e1c8db1dfea186f0bf6016bb1bf --- /dev/null +++ b/src/linked_list/simple_linked_list.rs @@ -0,0 +1,173 @@ + +pub struct Node{ + pub value : T, + pub next: Option>>, +} + +pub struct SimpleLinkedList { + + pub head: Option>>, +} + + +impl SimpleLinkedList { + pub fn new() -> Self { + Self { + head:None, + } + } + // You may be wondering why it's necessary to have is_empty() + // when it can easily be determined from len(). + // It's good custom to have both because len() can be expensive for some types, + // whereas is_empty() is almost always cheap. + // (Also ask yourself whether len() is expensive for SimpleLinkedList) + pub fn is_empty(&self) -> bool { + if self.head.is_none() { + return true; + }else{ + return false; + } + } + + pub fn len(&self) -> usize { + let mut res=0; + let mut temp=&self.head; + while let Some(node) = temp { + res += 1; + temp = &node.next; + } + return res; + } + + pub fn push(&mut self, element: T) { + let new_node = Box::new(Node { + value: element, + next: self.head.take(), + }); + self.head = Some(new_node); + } + + // 删除链表的头节点并返回其值 + pub fn pop(&mut self) -> Option { + self.head.take().map(|node| { + self.head = node.next; + node.value + }) + } + + pub fn peek(&self) -> Option<&T> { + self.head.as_ref().map(|node| &node.value) + } + + #[must_use] + pub fn rev(self) -> SimpleLinkedList { + let mut new_head=None; + let mut temp=self.head; + while let Some(node) = temp { + let new_node=Box::new(Node{value:node.value,next:new_head}); + new_head=Option::Some(new_node); + temp=node.next; + } + return SimpleLinkedList { + head:new_head}; + } +} + +impl FromIterator for SimpleLinkedList { + fn from_iter>(_iter: I) -> Self { + let mut list = SimpleLinkedList::new(); + for item in _iter { + list.push(item); + } + list + } +} + +// In general, it would be preferable to implement IntoIterator for SimpleLinkedList +// instead of implementing an explicit conversion to a vector. This is because, together, +// FromIterator and IntoIterator enable conversion between arbitrary collections. +// +// The reason this exercise's API includes an explicit conversion to Vec instead +// of IntoIterator is that implementing that interface is fairly complicated, and +// demands more of the student than we expect at this point in the track. +// +// Please note that the "front" of the linked list should correspond to the "back" +// of the vector as far as the tests are concerned. +impl From> for Vec { + fn from(mut _linked_list: SimpleLinkedList) -> Vec { + let mut vec = Vec::new(); + while let Some(value) = _linked_list.pop() { + vec.push(value); + } + vec.reverse(); + vec + } +} + + + +# [cfg(test)] +mod tests { + use super::*; + + #[test] + fn into_vector(){ + let mut v = Vec::new(); + let mut s = SimpleLinkedList::new(); + for i in 1..4 { + v.push(i); + s.push(i); + } + let s_as_vec: Vec = s.into(); + assert_eq!(v, s_as_vec); + } + + #[test] + fn slice(){ + let mut array = vec!["1", "2", "3", "4"]; + let mut list: SimpleLinkedList<_> = array.drain(..).collect(); + assert_eq!(list.pop(), Some("4")); + assert_eq!(list.pop(), Some("3")); + assert_eq!(list.pop(), Some("2")); + assert_eq!(list.pop(), Some("1")); + } + + #[test] + fn is_empty(){ + let mut array = vec!["1", "2", "3", "4"]; + let mut list: SimpleLinkedList<_> = array.drain(..).collect(); + assert_eq!(list.pop(), Some("4")); + assert_eq!(list.pop(), Some("3")); + assert_eq!(list.pop(), Some("2")); + assert_eq!(list.pop(), Some("1")); + } + + #[test] + fn new_list_is_empty() { + let list: SimpleLinkedList = SimpleLinkedList::new(); + assert_eq!(list.len(), 0, "list's length must be 0"); + } + + #[test] + fn push_and_pop(){ + let mut list: SimpleLinkedList = SimpleLinkedList::new(); + list.push(1); + list.push(2); + assert_eq!(list.pop(), Some(2), "Element must be 2"); + assert_eq!(list.pop(), Some(1), "Element must be 1"); + assert_eq!(list.pop(), None, "No element should be contained in list"); + } + #[test] + fn reverse(){ + let mut list: SimpleLinkedList = SimpleLinkedList::new(); + list.push(1); + list.push(2); + list.push(3); + let mut rev_list = list.rev(); + assert_eq!(rev_list.pop(), Some(1)); + assert_eq!(rev_list.pop(), Some(2)); + assert_eq!(rev_list.pop(), Some(3)); + assert_eq!(rev_list.pop(), None); + } + +} \ No newline at end of file diff --git a/src/math/perfect_square.rs b/src/math/perfect_square.rs index 7b0f69976c49fdf1beaf937aa409a615c1ca721d..c683b7cf47afbb24705b525f04173a83bfd779b3 100644 --- a/src/math/perfect_square.rs +++ b/src/math/perfect_square.rs @@ -9,6 +9,14 @@ pub fn perfect_square(num: i32) -> bool { sqrt_num * sqrt_num == num } +pub fn i32_midpoint(a:i32,b:i32)->i32{ + if a bool { if n < 0 { return false; @@ -18,7 +26,7 @@ pub fn perfect_square_binary_search(n: i32) -> bool { let mut right = n; while left <= right { - let mid = i32::midpoint(left, right); + let mid = i32_midpoint(left, right); let mid_squared = mid * mid; match mid_squared.cmp(&n) {