From 9e03e1e2a2c34f98c0aa0fecdd5b6560d1a62a92 Mon Sep 17 00:00:00 2001 From: why <435371447@qq.com> Date: Tue, 16 Apr 2024 19:45:41 +0800 Subject: [PATCH] update --- exercises/algorithm/algorithm1.rs | 61 +++++++++++++++++++++++------- exercises/algorithm/algorithm10.rs | 31 ++++++++++++++- exercises/algorithm/algorithm2.rs | 14 ++++++- exercises/algorithm/algorithm3.rs | 11 +++++- exercises/algorithm/algorithm4.rs | 35 ++++++++++++++++- exercises/algorithm/algorithm5.rs | 22 +++++++++-- exercises/algorithm/algorithm6.rs | 10 ++++- exercises/algorithm/algorithm7.rs | 22 +++++++++-- exercises/algorithm/algorithm8.rs | 21 ++++++++-- exercises/algorithm/algorithm9.rs | 59 +++++++++++++++++++++++++++-- 10 files changed, 251 insertions(+), 35 deletions(-) diff --git a/exercises/algorithm/algorithm1.rs b/exercises/algorithm/algorithm1.rs index f7a99bf..9d43a39 100644 --- a/exercises/algorithm/algorithm1.rs +++ b/exercises/algorithm/algorithm1.rs @@ -2,19 +2,25 @@ single linked list merge This problem requires you to merge two ordered singly linked lists into one ordered singly linked list */ -// I AM NOT DONE + use std::fmt::{self, Display, Formatter}; use std::ptr::NonNull; use std::vec::*; #[derive(Debug)] -struct Node { +struct Node +where + T: Ord + Clone + Display, +{ val: T, next: Option>>, } -impl Node { +impl Node +where + T: Ord + Clone + Display, +{ fn new(t: T) -> Node { Node { val: t, @@ -23,19 +29,28 @@ impl Node { } } #[derive(Debug)] -struct LinkedList { +struct LinkedList +where + T: Ord + Clone + Display, +{ length: u32, start: Option>>, end: Option>>, } -impl Default for LinkedList { +impl Default for LinkedList +where + T: Ord + Clone + Display, +{ fn default() -> Self { Self::new() } } -impl LinkedList { +impl LinkedList +where + T: Ord + Clone + Display, +{ pub fn new() -> Self { Self { length: 0, @@ -72,17 +87,37 @@ impl LinkedList { pub fn merge(list_a:LinkedList,list_b:LinkedList) -> Self { //TODO - Self { - length: 0, - start: None, - end: None, + let mut result = LinkedList::new(); + let mut current_a = list_a.start; + let mut current_b = list_b.start; + + while let (Some(node_a), Some(node_b)) = (current_a, current_b) { + unsafe { + if (*node_a.as_ptr()).val <= (*node_b.as_ptr()).val { + result.add((*node_a.as_ptr()).val.clone()); + current_a = (*node_a.as_ptr()).next; + } else { + result.add((*node_b.as_ptr()).val.clone()); + current_b = (*node_b.as_ptr()).next; + } + } } - } + + let mut remaining = if current_a.is_some() { current_a } else { current_b }; + while let Some(node) = remaining { + unsafe { + result.add((*node.as_ptr()).val.clone()); + remaining = (*node.as_ptr()).next; + } + } + + result + } } impl Display for LinkedList where - T: Display, + T: Ord + Clone + Display, { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self.start { @@ -94,7 +129,7 @@ where impl Display for Node where - T: Display, + T: Ord + Clone + Display, { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self.next { diff --git a/exercises/algorithm/algorithm10.rs b/exercises/algorithm/algorithm10.rs index a2ad731..6df5a14 100644 --- a/exercises/algorithm/algorithm10.rs +++ b/exercises/algorithm/algorithm10.rs @@ -2,7 +2,7 @@ graph This problem requires you to implement a basic graph functio */ -// I AM NOT DONE + use std::collections::{HashMap, HashSet}; use std::fmt; @@ -30,6 +30,17 @@ impl Graph for UndirectedGraph { } fn add_edge(&mut self, edge: (&str, &str, i32)) { //TODO + let (node1, node2, weight) = edge; + + // 给node1添加到node2的边 + self.adjacency_table.entry(node1.to_string()) + .or_insert_with(Vec::new) + .push((node2.to_string(), weight)); + + // 由于是无向图,还需要给node2添加到node1的边 + self.adjacency_table.entry(node2.to_string()) + .or_insert_with(Vec::new) + .push((node1.to_string(), weight)); } } pub trait Graph { @@ -38,10 +49,26 @@ pub trait Graph { fn adjacency_table(&self) -> &HashMap>; fn add_node(&mut self, node: &str) -> bool { //TODO - true + if self.adjacency_table_mutable().contains_key(node) { + false + } else { + self.adjacency_table_mutable().insert(node.to_string(), Vec::new()); + true + } } fn add_edge(&mut self, edge: (&str, &str, i32)) { //TODO + let (node1, node2, weight) = edge; + + // 给node1添加到node2的边 + self.adjacency_table_mutable().entry(node1.to_string()) + .or_insert_with(Vec::new) + .push((node2.to_string(), weight)); + + // 由于是无向图,还需要给node2添加到node1的边 + self.adjacency_table_mutable().entry(node2.to_string()) + .or_insert_with(Vec::new) + .push((node1.to_string(), weight)); } fn contains(&self, node: &str) -> bool { self.adjacency_table().get(node).is_some() diff --git a/exercises/algorithm/algorithm2.rs b/exercises/algorithm/algorithm2.rs index 08720ff..28ecbe2 100644 --- a/exercises/algorithm/algorithm2.rs +++ b/exercises/algorithm/algorithm2.rs @@ -2,7 +2,7 @@ double linked list reverse This problem requires you to reverse a doubly linked list */ -// I AM NOT DONE + use std::fmt::{self, Display, Formatter}; use std::ptr::NonNull; @@ -74,6 +74,18 @@ impl LinkedList { } pub fn reverse(&mut self){ // TODO + let mut current = self.start; + while let Some(mut current_node) = current { + // 交换当前节点的 next 和 prev + unsafe { + let mut node = current_node.as_mut(); + std::mem::swap(&mut node.prev, &mut node.next); + } + // 移动到原来的 prev 节点,现在是 next + current = unsafe { current_node.as_ref().prev }; + } + // 交换链表的 start 和 end + std::mem::swap(&mut self.start, &mut self.end); } } diff --git a/exercises/algorithm/algorithm3.rs b/exercises/algorithm/algorithm3.rs index 37878d6..fe87897 100644 --- a/exercises/algorithm/algorithm3.rs +++ b/exercises/algorithm/algorithm3.rs @@ -3,10 +3,17 @@ This problem requires you to implement a sorting algorithm you can use bubble sorting, insertion sorting, heap sorting, etc. */ -// I AM NOT DONE -fn sort(array: &mut [T]){ + +fn sort(array: &mut [T]){ //TODO + for i in 0..array.len() { + for j in 0..array.len() - i - 1 { + if array[j] > array[j + 1] { + array.swap(j, j + 1); + } + } + } } #[cfg(test)] mod tests { diff --git a/exercises/algorithm/algorithm4.rs b/exercises/algorithm/algorithm4.rs index 271b772..a569863 100644 --- a/exercises/algorithm/algorithm4.rs +++ b/exercises/algorithm/algorithm4.rs @@ -3,7 +3,7 @@ This problem requires you to implement a basic interface for a binary tree */ -//I AM NOT DONE + use std::cmp::Ordering; use std::fmt::Debug; @@ -51,12 +51,19 @@ where // Insert a value into the BST fn insert(&mut self, value: T) { //TODO + match self.root { + Some(ref mut node) => node.insert(value), + None => self.root = Some(Box::new(TreeNode::new(value))), + } } // Search for a value in the BST fn search(&self, value: T) -> bool { //TODO - true + match &self.root { + Some(node) => node.search(&value), + None => false, + } } } @@ -67,6 +74,30 @@ where // Insert a node into the tree fn insert(&mut self, value: T) { //TODO + match value.cmp(&self.value) { + Ordering::Less => { + if let Some(ref mut left) = self.left { + left.insert(value); + } else { + self.left = Some(Box::new(TreeNode::new(value))); + } + }, + Ordering::Greater => { + if let Some(ref mut right) = self.right { + right.insert(value); + } else { + self.right = Some(Box::new(TreeNode::new(value))); + } + }, + Ordering::Equal => {} // 如果值相等,我们不做任何操作,也可以在这里处理重复值 + } + } + fn search(&self, value: &T) -> bool { + match value.cmp(&self.value) { + Ordering::Equal => true, + Ordering::Less => self.left.as_ref().map_or(false, |node| node.search(value)), + Ordering::Greater => self.right.as_ref().map_or(false, |node| node.search(value)), + } } } diff --git a/exercises/algorithm/algorithm5.rs b/exercises/algorithm/algorithm5.rs index 8f206d1..1e805a5 100644 --- a/exercises/algorithm/algorithm5.rs +++ b/exercises/algorithm/algorithm5.rs @@ -3,7 +3,7 @@ This problem requires you to implement a basic BFS algorithm */ -//I AM NOT DONE + use std::collections::VecDeque; // Define a graph @@ -27,10 +27,24 @@ impl Graph { // Perform a breadth-first search on the graph, return the order of visited nodes fn bfs_with_return(&self, start: usize) -> Vec { - - //TODO - let mut visit_order = vec![]; + let mut visited = vec![false; self.adj.len()]; // Track visited nodes + let mut queue = VecDeque::new(); + + // Start BFS from the given start node + visited[start] = true; + queue.push_back(start); + + while let Some(node) = queue.pop_front() { + visit_order.push(node); + for &neighbor in &self.adj[node] { + if !visited[neighbor] { + visited[neighbor] = true; + queue.push_back(neighbor); + } + } + } + visit_order } } diff --git a/exercises/algorithm/algorithm6.rs b/exercises/algorithm/algorithm6.rs index 813146f..8c58ef3 100644 --- a/exercises/algorithm/algorithm6.rs +++ b/exercises/algorithm/algorithm6.rs @@ -3,7 +3,7 @@ This problem requires you to implement a basic DFS traversal */ -// I AM NOT DONE + use std::collections::HashSet; struct Graph { @@ -24,6 +24,14 @@ impl Graph { fn dfs_util(&self, v: usize, visited: &mut HashSet, visit_order: &mut Vec) { //TODO + visited.insert(v); // 标记当前节点为已访问 + visit_order.push(v); // 将当前节点加入访问顺序列表 + + for &i in &self.adj[v] { + if !visited.contains(&i) { // 对于每一个未访问的邻接节点 + self.dfs_util(i, visited, visit_order); // 递归访问 + } + } } // Perform a depth-first search on the graph, return the order of visited nodes diff --git a/exercises/algorithm/algorithm7.rs b/exercises/algorithm/algorithm7.rs index e0c3a5a..efd701d 100644 --- a/exercises/algorithm/algorithm7.rs +++ b/exercises/algorithm/algorithm7.rs @@ -3,7 +3,7 @@ This question requires you to use a stack to achieve a bracket match */ -// I AM NOT DONE + #[derive(Debug)] struct Stack { size: usize, @@ -32,7 +32,12 @@ impl Stack { } fn pop(&mut self) -> Option { // TODO - None + if self.size > 0 { + self.size -= 1; + self.data.pop() + } else { + None + } } fn peek(&self) -> Option<&T> { if 0 == self.size { @@ -102,7 +107,18 @@ impl<'a, T> Iterator for IterMut<'a, T> { fn bracket_match(bracket: &str) -> bool { //TODO - true + let mut stack = Stack::new(); + for c in bracket.chars() { + match c { + '(' | '{' | '[' => stack.push(c), + ')' => if stack.pop() != Some('(') { return false; }, + '}' => if stack.pop() != Some('{') { return false; }, + ']' => if stack.pop() != Some('[') { return false; }, + _ => {}, + } + } + + stack.is_empty() } #[cfg(test)] diff --git a/exercises/algorithm/algorithm8.rs b/exercises/algorithm/algorithm8.rs index d1d183b..ac94e9a 100644 --- a/exercises/algorithm/algorithm8.rs +++ b/exercises/algorithm/algorithm8.rs @@ -2,7 +2,7 @@ queue This question requires you to use queues to implement the functionality of the stac */ -// I AM NOT DONE + #[derive(Debug)] pub struct Queue { @@ -68,14 +68,29 @@ impl myStack { } pub fn push(&mut self, elem: T) { //TODO + // 元素首先入队到q2 + self.q2.enqueue(elem); + + // 将q1中的所有元素转移到q2 + while !self.q1.is_empty() { + if let Ok(data) = self.q1.dequeue() { + self.q2.enqueue(data); + } + } + + // 交换q1和q2 + std::mem::swap(&mut self.q1, &mut self.q2); } pub fn pop(&mut self) -> Result { //TODO - Err("Stack is empty") + if self.q1.is_empty() { + return Err("Stack is empty"); + } + self.q1.dequeue() } pub fn is_empty(&self) -> bool { //TODO - true + self.q1.is_empty() } } diff --git a/exercises/algorithm/algorithm9.rs b/exercises/algorithm/algorithm9.rs index 6c8021a..95796b1 100644 --- a/exercises/algorithm/algorithm9.rs +++ b/exercises/algorithm/algorithm9.rs @@ -2,7 +2,7 @@ heap This question requires you to implement a binary heap function */ -// I AM NOT DONE + use std::cmp::Ord; use std::default::Default; @@ -37,7 +37,18 @@ where } pub fn add(&mut self, value: T) { - //TODO + self.items.push(value); + self.count += 1; + let mut idx = self.count; + while idx > 1 { + let parent_idx = self.parent_idx(idx); // 提前计算父节点索引 + if (self.comparator)(&self.items[idx], &self.items[parent_idx]) { + self.items.swap(idx, parent_idx); // 使用预存的父节点索引进行swap + idx = parent_idx; + } else { + break; + } + } } fn parent_idx(&self, idx: usize) -> usize { @@ -58,7 +69,19 @@ where fn smallest_child_idx(&self, idx: usize) -> usize { //TODO - 0 + let left_idx = self.left_child_idx(idx); + let right_idx = self.right_child_idx(idx); + if right_idx <= self.count { + if (self.comparator)(&self.items[right_idx], &self.items[left_idx]) { + right_idx + } else { + left_idx + } + } else if left_idx <= self.count { + left_idx + } else { + idx // 当没有子节点时,返回自身的索引(不过通常不会用到) + } } } @@ -85,7 +108,35 @@ where fn next(&mut self) -> Option { //TODO - None + if self.count == 0 { + return None; + } + + // 弹出堆顶元素,这是最小或最大元素 + let result = self.items.swap_remove(1); + self.count -= 1; + + if self.count > 0 { + // 从数组末尾取出最后一个元素,并将其重新插入到堆的顶部 + let last_item = self.items.pop().unwrap(); + if !self.items.is_empty() { + self.items.insert(1, last_item); + } + + // 重新调整堆 + let mut idx = 1; + while self.children_present(idx) { + let swap_idx = self.smallest_child_idx(idx); + if (self.comparator)(&self.items[swap_idx], &self.items[idx]) { + self.items.swap(idx, swap_idx); + idx = swap_idx; + } else { + break; + } + } + } + + Some(result) } }