rust学习笔记9-结构体与206.反转链表

结构体

rust不是面向对象语言,没有类(class),主要采用结构体(struct)来处理结构化数据,这点与go语言相似。

基本使用

rust 复制代码
struct Person {
    name: String,
    age: u32,
    height: f64,
}

fn main() {
    let person = Person {
        name: String::from("张三"),
        age: 34,
        height: 175.0,
    };

    println!("姓名: {}, 年龄: {}, 身高: {}", person.name, person.age, person.height);
}
  1. 结构体的方法

通过 impl 块为结构体定义方法:

rust 复制代码
struct Person {
    name: String,
    age: u32,
    height: f64,
}

impl Person {
    // 关联函数(类似构造函数)
    fn new(name: &str, age: u32, height: f64) -> Person {
        Person {
            name: String::from(name),
            age,
            height,
        }
    }

    // 方法:打印信息
    fn greet(&self) {
        println!("我是: {}, 年龄: {}, 身高: {}", self.name, self.age, self.height);

    }

    // 方法:修改年龄
    fn celebrate_birthday(&mut self, age: u32) {
        self.age = age;
        println!("Happy Birthday! Now I am {} years old.", self.age);
    }
}

fn main() {
    let mut person = Person::new("小红", 25, 160.0);

    person.greet(); // 调用方法
    person.celebrate_birthday(24); // 修改年龄
    person.greet();
}

3.结构体与所有权

Rust 的所有权规则同样适用于结构体。如果结构体包含拥有所有权的字段(如 String 或 Vec),当结构体被移动时,这些字段的所有权也会被转移。

rust 复制代码
struct Person {
    name: String,
}

fn main() {
    let person = Person {
        name: String::from("小李"),
    };

    let another_person = person; // 所有权转移

    println!("{}", person.name); // 错误:`person` 已经被移动
}

4.rust结构体的可见性

结构体本身默认私有,用 pub 使其公有,这点与go语言不太一样,go是才用首字母是否大写来确定是否公有

rust 复制代码
pub struct PublicStruct {
    pub public_field: i32,
    private_field: i32,  // 默认私有
}

5.应用练习

206. 反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

复制代码
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例 2:

复制代码
输入:head = [1,2]
输出:[2,1]

示例 3:

复制代码
输入:head = []
输出:[]

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

**进阶:**链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?

(1)先定义数据库结构,直接从力扣上获取

rust 复制代码
 //Definition for singly-linked list.
 #[derive(PartialEq, Eq, Clone, Debug)]
 pub struct ListNode {
   pub val: i32,
   pub next: Option<Box<ListNode>>
 }
 
 impl ListNode {
   #[inline]
   fn new(val: i32) -> Self {
     ListNode {
       next: None,
       val
     }
   }
 }

注 Box<T> 是 Rust 中最简单的智能指针之一,它允许在堆上分配一块内存,并将值存储在这个内存中,目前智能指针还没学,暂时先了解一下,不用深究

(2)节点为空判断,由于 Rust 不支持 null ,这就很难受了,不光链表,后面的栈、队列、二叉树等都免不了要判断为空的情况,这怎么办呢,那就是用上一篇说的,用Option枚举类型,用Option可以有效处理节点为空的情况,可以用if也可以用match模式匹配,考虑目前还不是很熟,match不易理解,先用if,后面再用match

rust 复制代码
fn main() { 

    // 创建单个节点
    let node1 = ListNode::new(1); // 值为 1 的节点
    println!("单个节点: {:?}", node1);
    let head = Some(Box::new(node1)); // 确保 head 是 Option<Box<ListNode>>
    if let Some(node) = head {
        println!("节点不为空, 值是: {}", node.val);
    } else {
        println!("节点为空");
    }
    //创建空节点
    let head :Option<Box<ListNode>> = None;
    if let Some(node) = head {
        println!("节点不为空, 值是: {}", node.val);
    } else {
        println!("节点为空");
    }
}

(3)解题原始版本

rust 复制代码
 pub fn reverse_list(head: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
    let mut cur = head;
    let mut pre: Option<Box<ListNode>> = None;
    loop {
        if let Some(mut node) = cur {
            // 使用 take 取出 node.next 的值,并将 node.next 设置为 None
            cur = node.next.take(); 
            node.next = pre;        // 将前一个节点赋值给当前节点的 next
            pre = Some(node);       // 更新 pre 为当前节点
            
        } else {
            break;
        }
    } 
    return pre;
    
}

简化版

rust 复制代码
pub fn reverse_list(head: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
    let mut cur = head;
    let mut pre: Option<Box<ListNode>> = None;
    while let Some(mut node) = cur.take() {
        cur = node.next;
        node.next = pre;  
        pre = Some(node);      
    }
    return pre;
}

运行结果

总结结构体是rust重要是数据结构,需要重点掌握,未来无论刷题还是做项目都会大量用到。再处理链表这类复杂的数据结构,特别是为空判断,可以使用Option枚举类型,来处理这种情况。

解题思路,首先先屏蔽一些不易理解的内容,如智能指针Box<T>、match模式匹配不易理解,先用if,递归等学到函数递归再用,然后逐个解决,先解决为空判断,然后再解题就很轻松了。

take函数

Option::take 的定义

rust 复制代码
pub fn take(&mut self) -> Option<T>

功能:从一个可变引用中取出当前的值,并将该 Option<T> 设置为 None。

返回值:返回当前的 Option<T> 值(可能是 Some(T) 或 None)。

通过这种方式,take 方法允许你在不破坏原始 Option<T> 的情况下,安全地获取其内部值。

cur.take(); // 使用 take 取出 cur的值,并将 cur设置为 None,这样所有权不用发生转移,特别适合处理链表这种复杂的数据结构,安全高效

相关推荐
优选资源分享7 小时前
PicGo v3.0.3 新版 | 开源免费图床工具
javascript·笔记·electron
星恒随风9 小时前
Linux线程概念详解:从分页存储、页表、MMU与TLB,深入理解线程和进程的区别与联系
linux·运维·笔记·学习·状态模式
qq_284274059 小时前
数控机床编程基础与坐标系:编程六步流程、程序号/程序段/程序字格式,与右手定则下车床铣床XYZ轴判定(含考点)
笔记·学习·自动化·制造
德林恩宝9 小时前
On-Policy Distillation(OPD)学习文档
人工智能·学习·机器学习·大模型·llm·大模型微调
问心无愧05139 小时前
[SUCTF 2019]EasySQL
笔记
ss2739 小时前
PG实战笔记 | 09 PostgreSQL psql客户端基本操作
数据库·笔记·postgresql
xxwl5859 小时前
区域赛分类题解
c++·笔记·学习·算法
成都蜀味缘餐饮技术培训学校12 小时前
油炸串串技术培训实战指南,核心食材选购与预处理标准
数据仓库·经验分享·笔记·课程设计·微信公众平台
摇滚侠12 小时前
《大模型应用开发实践:基于 Spring AI+DeepSeek 实现》第 11 章 大模型技术概览 阅读笔记 1
人工智能·笔记·spring
xxwl58514 小时前
区域赛算法模版第八章---贪心(Greedy)
c++·笔记·学习·算法