Skip to content

Commit fe82888

Browse files
committed
update
1 parent ade0692 commit fe82888

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+822
-227
lines changed

exercises/algorithm/algorithm1.rs

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
single linked list merge
33
This problem requires you to merge two ordered singly linked lists into one ordered singly linked list
44
*/
5-
// I AM NOT DONE
5+
//
66

77
use std::fmt::{self, Display, Formatter};
88
use std::ptr::NonNull;
@@ -47,7 +47,7 @@ impl<T> LinkedList<T> {
4747
pub fn add(&mut self, obj: T) {
4848
let mut node = Box::new(Node::new(obj));
4949
node.next = None;
50-
let node_ptr = Some(unsafe { NonNull::new_unchecked(Box::into_raw(node)) });
50+
let node_ptr = NonNull::new(Box::into_raw(node));
5151
match self.end {
5252
None => self.start = node_ptr,
5353
Some(end_ptr) => unsafe { (*end_ptr.as_ptr()).next = node_ptr },
@@ -70,13 +70,57 @@ impl<T> LinkedList<T> {
7070
}
7171
}
7272
pub fn merge(list_a:LinkedList<T>,list_b:LinkedList<T>) -> Self
73-
{
73+
7474
//TODO
75-
Self {
76-
length: 0,
77-
start: None,
78-
end: None,
79-
}
75+
where
76+
T: Ord+Clone, // 要求 T 实现 Ord 特质,支持比较大小
77+
{
78+
let mut merged_list = LinkedList::new();
79+
// 初始化两个指针,指向两个链表的头节点
80+
let mut ptr_a = list_a.start;
81+
let mut ptr_b = list_b.start;
82+
83+
// 双指针循环比较,直到其中一个链表遍历完毕
84+
while let (Some(a), Some(b)) = (ptr_a, ptr_b) {
85+
let a_node = unsafe { a.as_ref() };
86+
let b_node = unsafe { b.as_ref() };
87+
88+
// 比较节点值,将较小的节点添加到新链表
89+
if a_node.val <= b_node.val {
90+
// 取出 ptr_a 指向的节点,添加到新链表
91+
merged_list.add(a_node.val.clone()); // 注意:需要 T 实现 Clone(下方补充约束)
92+
// 移动 ptr_a 到下一个节点
93+
ptr_a = a_node.next;
94+
} else {
95+
// 取出 ptr_b 指向的节点,添加到新链表
96+
merged_list.add(b_node.val.clone());
97+
// 移动 ptr_b 到下一个节点
98+
ptr_b = b_node.next;
99+
}
100+
}
101+
102+
// 处理 list_a 剩余的节点
103+
while let Some(a) = ptr_a {
104+
let a_node = unsafe { a.as_ref() };
105+
merged_list.add(a_node.val.clone());
106+
ptr_a = a_node.next;
107+
}
108+
109+
// 处理 list_b 剩余的节点
110+
while let Some(b) = ptr_b {
111+
let b_node = unsafe { b.as_ref() };
112+
merged_list.add(b_node.val.clone());
113+
ptr_b = b_node.next;
114+
}
115+
116+
merged_list
117+
118+
119+
// Self {
120+
// length: 0,
121+
// start: None,
122+
// end: None,
123+
// }
80124
}
81125
}
82126

@@ -104,6 +148,9 @@ where
104148
}
105149
}
106150

151+
// 为了支持 val.clone(),需要为 LinkedList<T> 的方法补充 Clone 约束
152+
impl<T: Clone + Ord> LinkedList<T> {}
153+
107154
#[cfg(test)]
108155
mod tests {
109156
use super::LinkedList;

exercises/algorithm/algorithm10.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
graph
33
This problem requires you to implement a basic graph functio
44
*/
5-
// I AM NOT DONE
5+
// I AM DONE
66

77
use std::collections::{HashMap, HashSet};
88
use std::fmt;
@@ -30,6 +30,22 @@ impl Graph for UndirectedGraph {
3030
}
3131
fn add_edge(&mut self, edge: (&str, &str, i32)) {
3232
//TODO
33+
let (from, to, weight) = edge;
34+
// 确保两个节点都存在(不存在则自动添加)
35+
self.add_node(from);
36+
self.add_node(to);
37+
38+
// 向 from 节点的邻接列表添加 to 节点和权重
39+
self.adjacency_table
40+
.get_mut(&from.to_string())
41+
.unwrap() // 已通过 add_node 确保存在,unwrap 安全
42+
.push((to.to_string(), weight));
43+
44+
// 向 to 节点的邻接列表添加 from 节点和权重(无向边双向性)
45+
self.adjacency_table
46+
.get_mut(&to.to_string())
47+
.unwrap() // 已通过 add_node 确保存在,unwrap 安全
48+
.push((from.to_string(), weight));
3349
}
3450
}
3551
pub trait Graph {
@@ -38,6 +54,10 @@ pub trait Graph {
3854
fn adjacency_table(&self) -> &HashMap<String, Vec<(String, i32)>>;
3955
fn add_node(&mut self, node: &str) -> bool {
4056
//TODO
57+
if self.contains(node) {
58+
return false;
59+
}
60+
self.adjacency_table_mutable().insert(node.to_string(), Vec::new());
4161
true
4262
}
4363
fn add_edge(&mut self, edge: (&str, &str, i32)) {

exercises/algorithm/algorithm2.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
double linked list reverse
33
This problem requires you to reverse a doubly linked list
44
*/
5-
// I AM NOT DONE
5+
66

77
use std::fmt::{self, Display, Formatter};
88
use std::ptr::NonNull;
@@ -50,7 +50,7 @@ impl<T> LinkedList<T> {
5050
let mut node = Box::new(Node::new(obj));
5151
node.next = None;
5252
node.prev = self.end;
53-
let node_ptr = Some(unsafe { NonNull::new_unchecked(Box::into_raw(node)) });
53+
let node_ptr = NonNull::new(Box::into_raw(node));
5454
match self.end {
5555
None => self.start = node_ptr,
5656
Some(end_ptr) => unsafe { (*end_ptr.as_ptr()).next = node_ptr },
@@ -74,6 +74,27 @@ impl<T> LinkedList<T> {
7474
}
7575
pub fn reverse(&mut self){
7676
// TODO
77+
// 处理空链表或只有一个节点的情况,直接返回
78+
if self.length <= 1 {
79+
return;
80+
}
81+
82+
// 临时指针,用于遍历链表
83+
let mut current = self.start;
84+
// 交换链表的头和尾
85+
std::mem::swap(&mut self.start, &mut self.end);
86+
87+
// 遍历每个节点,交换 prev 和 next 指针
88+
while let Some(mut cur_ptr) = current {
89+
unsafe {
90+
// 获取当前节点的可变引用
91+
let cur_node = cur_ptr.as_mut();
92+
// 交换当前节点的 prev 和 next
93+
std::mem::swap(&mut cur_node.prev, &mut cur_node.next);
94+
// 移动到下一个节点(注意:因为 prev/next 已交换,现在要走 prev 指针)
95+
current = cur_node.prev;
96+
}
97+
}
7798
}
7899
}
79100

exercises/algorithm/algorithm3.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,38 @@
33
This problem requires you to implement a sorting algorithm
44
you can use bubble sorting, insertion sorting, heap sorting, etc.
55
*/
6-
// I AM NOT DONE
6+
//
77

8-
fn sort<T>(array: &mut [T]){
8+
fn sort<T:Ord>(array: &mut [T]){
99
//TODO
10+
// 如果数组长度 <= 1,直接返回(已经有序)
11+
if array.len() <= 1 {
12+
return;
13+
}
14+
15+
let mut swapped;
16+
let mut n = array.len();
17+
18+
// 冒泡排序核心逻辑
19+
loop {
20+
swapped = false;
21+
// 遍历未排序部分,比较相邻元素
22+
for i in 1..n {
23+
// 如果前一个元素大于后一个,交换位置
24+
if array[i - 1] > array[i] {
25+
array.swap(i - 1, i);
26+
swapped = true;
27+
}
28+
}
29+
30+
// 每轮结束后,最后一个元素已排序,缩小遍历范围
31+
n -= 1;
32+
33+
// 如果本轮没有交换,说明数组已完全有序,退出循环
34+
if !swapped {
35+
break;
36+
}
37+
}
1038
}
1139
#[cfg(test)]
1240
mod tests {

exercises/algorithm/algorithm4.rs

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
This problem requires you to implement a basic interface for a binary tree
44
*/
55

6-
//I AM NOT DONE
6+
77
use std::cmp::Ordering;
88
use std::fmt::Debug;
99

10-
1110
#[derive(Debug)]
1211
struct TreeNode<T>
1312
where
@@ -37,40 +36,70 @@ where
3736
right: None,
3837
}
3938
}
39+
40+
// 辅助方法:在当前节点的子树中插入值
41+
fn insert(&mut self, value: T) {
42+
match value.cmp(&self.value) {
43+
// 插入值小于当前节点值 → 插入左子树
44+
Ordering::Less => {
45+
if let Some(ref mut left_node) = self.left {
46+
left_node.insert(value);
47+
} else {
48+
self.left = Some(Box::new(TreeNode::new(value)));
49+
}
50+
}
51+
// 插入值大于当前节点值 → 插入右子树
52+
Ordering::Greater => {
53+
if let Some(ref mut right_node) = self.right {
54+
right_node.insert(value);
55+
} else {
56+
self.right = Some(Box::new(TreeNode::new(value)));
57+
}
58+
}
59+
// 相等则不处理(BST 不存储重复值)
60+
Ordering::Equal => (),
61+
}
62+
}
4063
}
4164

4265
impl<T> BinarySearchTree<T>
4366
where
4467
T: Ord,
4568
{
46-
4769
fn new() -> Self {
4870
BinarySearchTree { root: None }
4971
}
5072

51-
// Insert a value into the BST
73+
// 插入值到 BST
5274
fn insert(&mut self, value: T) {
53-
//TODO
75+
if let Some(ref mut root_node) = self.root {
76+
// 根节点存在,调用节点的 insert 方法
77+
root_node.insert(value);
78+
} else {
79+
// 根节点为空,新建根节点
80+
self.root = Some(Box::new(TreeNode::new(value)));
81+
}
5482
}
5583

56-
// Search for a value in the BST
84+
// 查找值是否存在于 BST
5785
fn search(&self, value: T) -> bool {
58-
//TODO
59-
true
60-
}
61-
}
62-
63-
impl<T> TreeNode<T>
64-
where
65-
T: Ord,
66-
{
67-
// Insert a node into the tree
68-
fn insert(&mut self, value: T) {
69-
//TODO
86+
// 从根节点开始查找
87+
let mut current = &self.root;
88+
while let Some(ref node) = current {
89+
match value.cmp(&node.value) {
90+
// 找到匹配值 → 返回 true
91+
Ordering::Equal => return true,
92+
// 查找值更小 → 去左子树找
93+
Ordering::Less => current = &node.left,
94+
// 查找值更大 → 去右子树找
95+
Ordering::Greater => current = &node.right,
96+
}
97+
}
98+
// 遍历完所有节点未找到 → 返回 false
99+
false
70100
}
71101
}
72102

73-
74103
#[cfg(test)]
75104
mod tests {
76105
use super::*;

exercises/algorithm/algorithm5.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
This problem requires you to implement a basic BFS algorithm
44
*/
55

6-
//I AM NOT DONE
6+
//
77
use std::collections::VecDeque;
88

99
// Define a graph
@@ -29,8 +29,37 @@ impl Graph {
2929
fn bfs_with_return(&self, start: usize) -> Vec<usize> {
3030

3131
//TODO
32+
// 处理空图/起点越界的情况(测试用例中起点都是合法的,此处做防御性处理)
33+
if start >= self.adj.len() {
34+
return vec![];
35+
}
36+
37+
// 1. 初始化访问标记数组:false 表示未访问,true 表示已访问
38+
let mut visited = vec![false; self.adj.len()];
39+
// 2. 初始化队列,用于存储待访问的节点
40+
let mut queue = VecDeque::new();
41+
// 3. 初始化访问顺序列表
3242

3343
let mut visit_order = vec![];
44+
45+
// 将起点加入队列并标记为已访问
46+
queue.push_back(start);
47+
visited[start] = true;
48+
49+
// 4. 循环处理队列中的节点
50+
while let Some(current) = queue.pop_front() {
51+
// 将当前节点加入访问顺序
52+
visit_order.push(current);
53+
54+
// 遍历当前节点的所有邻接节点
55+
for &neighbor in &self.adj[current] {
56+
// 若邻接节点未被访问,则标记并加入队列
57+
if !visited[neighbor] {
58+
visited[neighbor] = true;
59+
queue.push_back(neighbor);
60+
}
61+
}
62+
}
3463
visit_order
3564
}
3665
}

0 commit comments

Comments
 (0)