【Rust入门知识点学与练】第15课:泛型 Generics 引语根据之前的课程进度第15课是泛型 Generics。这是一个文本创作类任务我需要按照之前课程的格式来编写泛型的教学内容包括知识点讲解、代码示例和练习题。知识点1泛型函数泛型让你写出适用于多种类型的代码避免重复// 不用泛型需要写多个函数fnlargest_i32(list:[i32])-i32{letmutlargestlist[0];foriteminlist[1..]{ifitemlargest{largestitem;}}largest}// 用泛型一个函数搞定所有类型// T: PartialOrd 表示 T 必须支持比较操作fnlargestT:PartialOrd(list:[T])-T{letmutlargestlist[0];foriteminlist[1..]{ifitemlargest{largestitem;}}largest}fnmain(){letnumbersvec![34,50,25,100,65];println!(最大数: {},largest(numbers));letcharsvec![y,m,a,q];println!(最大字符: {},largest(chars));letfloatsvec![1.1,3.3,2.2];println!(最大浮点: {},largest(floats));}知识点2泛型结构体// 泛型结构体Point 可以存储任何类型的坐标structPointT{x:T,y:T,}implTPointT{fnnew(x:T,y:T)-Self{Point{x,y}}fnx(self)-T{self.x}fny(self)-T{self.y}}// 可以为特定类型实现额外方法implPointf64{fndistance_from_origin(self)-f64{(self.x.powi(2)self.y.powi(2)).sqrt()}}fnmain(){letinteger_pointPoint::new(5,10);println!(整数点: ({}, {}),integer_point.x(),integer_point.y());letfloat_pointPoint::new(3.0,4.0);println!(浮点点: ({}, {}),float_point.x(),float_point.y());println!(到原点距离: {},float_point.distance_from_origin());// 5.0}知识点3多个泛型参数structPairT,U{first:T,second:U,}implT,UPairT,U{fnnew(first:T,second:U)-Self{Pair{first,second}}}implT:std::fmt::Display,U:std::fmt::DisplayPairT,U{// 只有当 T 和 U 都实现了 Display 时这个方法才可用fndisplay(self){println!(({}, {}),self.first,self.second);}}fnmain(){letpPair::new(hello,42);p.display();// (hello, 42)letp2Pair::new(3.14,true);p2.display();// (3.14, true)}知识点4trait 约束用 where 子句让约束更清晰usestd::fmt;// 普通写法fnnotify1T:fmt::DisplayClone(item:T){println!(通知: {},item.clone());}// where 写法更清晰fnnotify2T,U(t:T,u:U)whereT:fmt::DisplayClone,U:fmt::DebugClone,{println!(T: {}, U: {:?},t.clone(),u.clone());}fnmain(){notify1(String::from(hello));notify2(String::from(hello),42);}知识点5返回实现了 trait 的类型usestd::fmt;// 返回实现了 Display 的任意类型fnreturns_displayable(flag:bool)-implfmt::Display{ifflag{String::from(hello)}else{42}// 注意上面这样写会报错// impl Trait 要求返回类型必须一致// 正确写法如下}// 正确两个分支返回相同类型fnreturns_string(flag:bool)-implfmt::Display{ifflag{String::from(true)}else{String::from(false)}}fnmain(){println!({},returns_string(true));println!({},returns_string(false));}核心规则概念 写法泛型函数 fn funcT: Trait(param: T)泛型结构体 struct Name { field: T }多泛型参数 struct NameT, Utrait 约束 T: Display Clonewhere 子句 where T: Display, U: Debug返回 trait 类型 fn func() - impl Trait调用泛型函数 类型自动推断或 func::(…)动手试试补全下面的代码usestd::fmt;// 补全定义一个泛型结构体 StackT内部用 VecT 存储数据// 实现以下方法// 1. new() - StackT 创建空栈// 2. push(mut self, item: T) 入栈// 3. pop(mut self) - OptionT 出栈// 4. peek(self) - OptionT 查看栈顶不弹出// 5. is_empty(self) - bool 是否为空// 6. size(self) - usize 栈中元素个数// 补全为 StackT 实现 Display traitT 需要实现 Display// 格式[底 - 顶]例如栈中有 1,2,33是栈顶输出 [1, 2, 3]fnmain(){// 补全创建一个整数栈依次压入 10, 20, 30// 打印栈内容期望: [10, 20, 30]// 打印栈大小期望: 3// 查看栈顶期望: Some(30)// 弹出栈顶并打印期望: 30// 再次打印栈内容期望: [10, 20]// 弹出所有元素再打印是否为空期望: true// 补全创建一个字符串栈压入 hello, world// 打印栈内容期望: [hello, world]}期望输出[10, 20, 30]大小: 3栈顶: Some(30)弹出: 30[10, 20]栈为空: true[hello, world]写好了贴过来没问题就进入第16课生命周期 Lifetimes 贴代码usestd::fmt;// 泛型栈结构体structStackT{data:VecT,}// 方法实现implTStackT{// 1. 创建空栈fnnew()-StackT{Stack{data:Vec::new()}}// 2. 入栈fnpush(mutself,item:T){self.data.push(item);}// 3. 出栈fnpop(mutself)-OptionT{self.data.pop()}// 4. 查看栈顶借用不获取所有权fnpeek(self)-OptionT{self.data.last()}// 5. 判断栈是否为空fnis_empty(self)-bool{self.data.is_empty()}// 6. 获取栈元素数量fnsize(self)-usize{self.data.len()}}// 实现 Display约束 T 必须实现 fmt::DisplayimplT:fmt::Displayfmt::DisplayforStackT{fnfmt(self,f:mutfmt::Formatter_)-fmt::Result{// 将每个元素转字符串用 , 连接letitems:VecStringself.data.iter().map(|x|format!({},x)).collect();write!(f,[{}],items.join(, ))}}fnmain(){// 整数栈测试letmutint_stackStack::new();int_stack.push(10);int_stack.push(20);int_stack.push(30);println!({},int_stack);println!(栈大小: {},int_stack.size());println!(栈顶: {:?},int_stack.peek());lettopint_stack.pop();println!(弹出: {:?},top);println!({},int_stack);// 清空栈int_stack.pop();int_stack.pop();println!(栈是否为空: {},int_stack.is_empty());// 字符串栈测试letmutstr_stackStack::new();str_stack.push(hello);str_stack.push(world);println!({},str_stack);}运行输出plaintext[10, 20, 30]栈大小: 3栈顶: Some(30)弹出: Some(30)[10, 20]栈是否为空: true[hello, world]核心知识点讲解1. 泛型 StackT 是类型参数栈可以存放任意类型 Stack 、 Stackstr 、 Stack 。泛型让一份代码支持多种数据类型不需要重复写多份栈实现。2. Vec 作为栈底层存储push 尾部追加 → 入栈pop 尾部删除 → 出栈last() 获取尾部元素的引用 → peek不会拿走所有权。3. 借用 vs 所有权pop(mut self) - Option 返回元素本身所有权转移栈里面就没有了peek(self) - OptionT 返回引用栈里面元素还在只是看一看。4. Display trait 实现implT:fmt::Displayfmt::DisplayforStackTT: fmt::Display 是trait 约束只有栈里面的元素类型T支持DisplayStack才能被 {} 打印。如果T没有实现Display就不能用println!(“{}”, stack)编译报错。5. 迭代器 map collectself.data.iter().map(|x|format!({},x)).collect()遍历栈里每一个元素转为字符串收集到一个字符串Vec最后用 join 拼接。拓展Rust标准库没有单独的Stack容器日常开发直接用Vec模拟栈push/pop/last和我们这道题一模一样。做完泛型栈泛型基础就过关了。需要一道泛型队列Queue练习题吗练习题泛型队列 QueueFIFO 先进先出题目要求使用 Rust 实现一个泛型队列 Queue底层用 Vec 存储实现队列的基础操作。队列先进先出(FIFO)队尾入队队头出队。1. 结构体定义Queue 内部字段 data: Vec2. 需要实现的方法2.1 new() - Self 创建空队列2.2 enqueue(mut self, item: T) 入队元素加到队尾vec.push2.3 dequeue(mut self) - Option 出队从队列头部删除并返回注意Vec 的 remove(0)删除索引0的元素数组头部删除性能差但初学练习就用这个简单实现2.4 front(self) - OptionT 查看队首元素不删除返回引用2.5 is_empty(self) - bool 队列是否为空2.6 len(self) - usize 返回队列元素个数3. 实现 Display trait约束 T: fmt::Display打印格式样例队列存 10,20,3010队首、30队尾→ [10, 20, 30]4. main 测试逻辑创建一个 i32 队列依次入队10、20、30打印队列内容 → [10, 20, 30]打印队列长度 → 3获取队首 front → Some(10)出队 dequeue打印弹出的值 → 10打印当前队列 → [20, 30]全部元素出队打印 is_empty → true新建字符串队列入队 “a” , “b” 打印队列 → [a, b]提示4.1. vec.remove(0) 移除第一个元素返回该元素队列为空调用remove(0)会panic不能直接用需要先判断队列是否为空再返回Option。4.2. 获取队首引用 self.data.first()4.3. Display 的实现思路和上一题 Stack 几乎一样。贴代码先自行编写完成后再看参考答案完整参考答案usestd::fmt;structQueueT{data:VecT,}implTQueueT{fnnew()-Self{Queue{data:Vec::new()}}// 入队队尾添加fnenqueue(mutself,item:T){self.data.push(item);}// 出队队头弹出空队列返回Nonefndequeue(mutself)-OptionT{ifself.is_empty(){None}else{Some(self.data.remove(0))}}// 获取队首元素的引用fnfront(self)-OptionT{self.data.first()}fnis_empty(self)-bool{self.data.is_empty()}fnlen(self)-usize{self.data.len()}}// Display 实现implT:fmt::Displayfmt::DisplayforQueueT{fnfmt(self,f:mutfmt::Formatter_)-fmt::Result{letstrs:VecStringself.data.iter().map(|v|format!({},v)).collect();write!(f,[{}],strs.join(, ))}}fnmain(){// i32队列测试letmutqQueue::new();q.enqueue(10);q.enqueue(20);q.enqueue(30);println!({},q);println!(队列长度: {},q.len());println!(队首: {:?},q.front());letoutq.dequeue();println!(出队元素: {:?},out);println!({},q);q.dequeue();q.dequeue();println!(队列是否为空: {},q.is_empty());// 字符串队列letmutstr_qQueue::new();str_q.enqueue(a);str_q.enqueue(b);println!({},str_q);}运行输出plaintext[10, 20, 30]队列长度: 3队首: Some(10)出队元素: Some(10)[20, 30]队列是否为空: true[a, b]知识点总结栈StackLIFO后进先出push/pop操作vec尾部性能很好 O(1)本版队列 remove(0) 数组头部删除时间复杂度O(n)元素很多的时候很慢工业级实现一般用双端队列VecDeque std::collections::VecDeque 两端增删都是O(1)。first() 获取第一个元素的引用对应栈的 last() 。泛型代码复用Queue一份实现支持i32、str、String等任意类型。拓展标准库双端队列 VecDeque 的基础用法工业版队列usestd::collections::VecDeque;fnmain(){letmutdqVecDeque::new();dq.push_back(10);// 入队尾部dq.pop_front();// 队头出队O(1)高性能}

相关新闻

最新新闻

全面预算管理体系框架与落地实践:从Excel到管理闭环

全面预算管理体系框架与落地实践:从Excel到管理闭环

简介:面向企业财务与经营管理人员,围绕全面预算管理体系的框架设计与实际落地,系统讲解从战略目标分解、预算编制、执行监控到差异分析的完整闭环。全篇以七大部分递进展开:先搭建总体框架,再剖析现行预算的常见问题&a…

2026/9/6 14:11:49
Pi_Agent实战:构建沙箱执行管理器与权限控制

Pi_Agent实战:构建沙箱执行管理器与权限控制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/6 14:11:49
南方NTS全站仪使用教程:从架站设站到测量放样实战全攻略

南方NTS全站仪使用教程:从架站设站到测量放样实战全攻略

简介:南方NTS全站仪使用教程PPT课件面向测绘、土木和建筑专业的初学者及一线测量人员,系统讲解全站仪的原理、分类和操作要点。课件先介绍全站仪作为三维坐标测量系统的核心构成,对比徕卡、蔡司、拓普康、索佳、尼康、宾得、南方测绘、苏光等…

2026/9/6 14:11:49
学术问卷设计量表开发与信效度检验完整指南

学术问卷设计量表开发与信效度检验完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/6 14:11:49
南方NTS全站仪实训教程:从原理到放样的关键操作与避坑指南

南方NTS全站仪实训教程:从原理到放样的关键操作与避坑指南

简介:南方NTS全站仪使用教程PPT课件是一份专业教学课件,系统讲解全站仪的定义、主流品牌与选型、使用注意事项,并重点拆解南方NTS系列的结构组成、显示屏符号、软键与星键操作。面向测量工程专业学生、测绘入门人员及需要快速掌握全站仪实操的…

2026/9/6 14:11:49
自动链条编结机课程设计:机构选型与参数计算全解析

自动链条编结机课程设计:机构选型与参数计算全解析

简介:机械原理课程设计《自动链条编结机》完整方案文档,面向机械类专业学生及课程设计指导者,也可为相关自动化机械设计提供借鉴。文档系统梳理了自动链条编结机的设计题目、加工要求与工艺分解,涵盖钢丝直径2.3~2.5mm、链节长度3…

2026/9/6 14:06:49