在计算机图形学、地理信息系统(GIS)、机器人路径规划等领域,Rust凸包算法是一个基础而重要的工具。本文将手把手教你如何用Rust语言实现经典的Andrew算法来求解点集的凸包,即使你是编程小白,也能轻松理解!
想象你有一堆钉子钉在木板上,然后用一根橡皮筋把它们全部围起来——橡皮筋绷紧后所形成的形状就是这些点的凸包(Convex Hull)。凸包是包含所有点的最小凸多边形。

Andrew 算法是 Graham 扫描法的一种变体,它通过分别构建凸包的上半部分和下半部分,时间复杂度为 O(n log n),易于理解和实现,非常适合初学者学习 计算几何 的入门。
首先,确保你已安装 Rust(可通过 rustup 安装)。然后在终端中运行:
cargo new convex_hull_tutorialcd convex_hull_tutorial我们先定义一个二维点的结构体,并实现必要的比较方法:
#[derive(Debug, Clone, Copy)]struct Point { x: i32, y: i32,}impl PartialEq for Point { fn eq(&self, other: &Self) -> bool { self.x == other.x && self.y == other.y }}impl Eq for Point {}impl PartialOrd for Point { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) }}impl Ord for Point { fn cmp(&self, other: &Self) -> std::cmp::Ordering { match self.x.cmp(&other.x) { std::cmp::Ordering::Equal => self.y.cmp(&other.y), other => other, } }} 这里我们让 Point 可以按 x 坐标排序,x 相同时按 y 排序,这是 Andrew 算法的前提。
叉积用于判断三个点的转向(左转、右转或共线):
fn cross(o: &Point, a: &Point, b: &Point) -> i32 { (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x)}- 如果结果 > 0:左转(逆时针)
- 如果结果 < 0:右转(顺时针)
- 如果结果 = 0:三点共线
fn convex_hull(mut points: Vec) -> Vec { if points.len() <= 1 { return points; } // 按 x(然后 y)排序 points.sort(); // 去重 points.dedup(); let n = points.len(); let mut hull = Vec::with_capacity(n); // 构建下凸壳 for i in 0..n { while hull.len() >= 2 { let last = hull.len() - 1; if cross(&hull[last - 1], &hull[last], &points[i]) <= 0 { hull.pop(); } else { break; } } hull.push(points[i]); } // 构建上凸壳 let lower_len = hull.len(); for i in (0..=n - 2).rev() { while hull.len() > lower_len { let last = hull.len() - 1; if cross(&hull[last - 1], &hull[last], &points[i]) <= 0 { hull.pop(); } else { break; } } hull.push(points[i]); } // 移除最后一个重复点(起点) if !hull.is_empty() { hull.pop(); } hull} 在 main.rs 中添加主函数进行测试:
fn main() { let points = vec![ Point { x: 0, y: 0 }, Point { x: 1, y: 1 }, Point { x: 2, y: 2 }, Point { x: 0, y: 2 }, Point { x: 2, y: 0 }, Point { x: 1, y: 0 }, ]; let hull = convex_hull(points); println!("凸包顶点: {:?}", hull);}运行程序:
cargo run你应该看到输出类似:
凸包顶点: [Point { x: 0, y: 0 }, Point { x: 2, y: 0 }, Point { x: 2, y: 2 }, Point { x: 0, y: 2 }]恭喜你!你已经成功用 Rust 实现了凸包算法。通过本教程,你不仅掌握了 Rust编程教程 中的重要实践,也深入理解了 计算几何 的核心思想。Andrew 算法简洁高效,是解决凸包问题的理想选择。
希望这篇关于 Rust凸包算法 和 Andrew算法 的教程对你有帮助!你可以尝试扩展功能,比如处理浮点坐标、可视化结果等。
本文由主机测评网于2025-12-06发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/2025123896.html