Recursion 调用此递归函数时如何避免堆栈溢出
我已经在Rust中实现了Ramer–Douglas–Peucker线简化算法,它在ε值>1.0时正确工作。但是,任何低于该值的值都会导致堆栈溢出。如何重写函数以避免这种情况Recursion 调用此递归函数时如何避免堆栈溢出,recursion,rust,Recursion,Rust,我已经在Rust中实现了Ramer–Douglas–Peucker线简化算法,它在ε值>1.0时正确工作。但是,任何低于该值的值都会导致堆栈溢出。如何重写函数以避免这种情况 // distance formula pub fn distance(start: &[f64; 2], end: &[f64; 2]) -> f64 { ((start[0] - end[0]).powf(2.) + (start[1] - end[1]).powf(2.)).sqrt()
// distance formula
pub fn distance(start: &[f64; 2], end: &[f64; 2]) -> f64 {
((start[0] - end[0]).powf(2.) + (start[1] - end[1]).powf(2.)).sqrt()
}
// perpendicular distance from a point to a line
pub fn point_line_distance(point: &[f64; 2], start: &[f64; 2], end: &[f64; 2]) -> f64 {
if start == end {
return distance(*&point, *&start);
} else {
let n = ((end[0] - start[0]) * (start[1] - point[1]) -
(start[0] - point[0]) * (end[1] - start[1]))
.abs();
let d = ((end[0] - start[0]).powf(2.0) + (end[1] - start[1]).powf(2.0)).sqrt();
n / d
}
}
// Ramer–Douglas-Peucker line simplification algorithm
pub fn rdp(points: &[[f64; 2]], epsilon: &f64) -> Vec<[f64; 2]> {
let mut dmax = 1.0;
let mut index: usize = 0;
let mut distance: f64;
for (i, _) in points.iter().enumerate().take(points.len() - 1).skip(1) {
distance = point_line_distance(&points[i],
&*points.first().unwrap(),
&*points.last().unwrap());
if distance > dmax {
index = i;
dmax = distance;
}
}
if dmax > *epsilon {
let mut intermediate = rdp(&points[..index + 1], &*epsilon);
intermediate.pop();
intermediate.extend_from_slice(&rdp(&points[index..], &*epsilon));
intermediate
} else {
vec![*points.first().unwrap(), *points.last().unwrap()]
}
}
fn main() {
let points = vec![[0.0, 0.0], [5.0, 4.0], [11.0, 5.5], [17.3, 3.2], [27.8, 0.1]];
// change this to &0.99 to overflow the stack
let foo: Vec<_> = rdp(&points, &1.0);
assert_eq!(foo, vec![[0.0, 0.0], [5.0, 4.0], [11.0, 5.5], [17.3, 3.2]]);
}
//距离公式
发布fn距离(起点:&[f64;2],终点:&[f64;2])->f64{
((start[0]-end[0]).powf(2.)+(start[1]-end[1]).powf(2.).sqrt()
}
//点到线的垂直距离
发布fn点线距离(点:&[f64;2],起点:&[f64;2],终点:&[f64;2])->f64{
如果开始=结束{
返回距离(*&点、*&起点);
}否则{
设n=((结束[0]-开始[0])*(开始[1]-点[1])-
(开始[0]-点[0])*(结束[1]-开始[1]))
.abs();
设d=((end[0]-start[0]).powf(2.0)+(end[1]-start[1]).powf(2.0)).sqrt();
不适用
}
}
//Ramer–Douglas Peucker直线简化算法
发布fn rdp(点:&[[f64;2]],ε:&f64)->Vec{
设mut dmax=1.0;
让mut索引:usize=0;
让mut距离:f64;
在points.iter().enumerate().take(points.len()-1.skip(1)中为(i,){
距离=点\线\距离(&点[i],
&*points.first().unwrap(),
&*points.last().unwrap());
如果距离>dmax{
指数=i;
dmax=距离;
}
}
如果dmax>*ε{
设mut intermediate=rdp(&points[…index+1],&*epsilon);
intermediate.pop();
中间。从_切片扩展_(&rdp(&points[index..,&*epsilon));
中间的
}否则{
vec![*点.first().unwrap(),*点.last().unwrap()]
}
}
fn main(){
让分数=vec![[0.0,0.0]、[5.0,4.0]、[11.0,5.5]、[17.3,3.2]、[27.8,0.1];
//将其更改为&0.99以使堆栈溢出
设foo:Vec=rdp(&points,&1.0);
断言(foo,vec![[0.0,0.0]、[5.0,4.0]、[11.0,5.5]、[17.3,3.2]);
}
查看rdp
的流程。它是一个递归函数,在dmax>epsilon
的条件下递归。因此,让我们按照这些变量逐步进行:
首先,我们将dmax
设置为1.0。然后,如果distance>dmax
,dmax
设置为distance
。因此,dmax
不可能小于1.0
然后,如果dmax>epsilon
,我们递归。如果epsilon<1.0,则始终会发生这种情况
如果我们查看上的算法,您可以看到dmax
应该从0.0开始
另一方面,您可以使用该函数使距离函数变得更好。看看
rdp
的流程。它是一个递归函数,在dmax>epsilon
的条件下递归。因此,让我们按照这些变量逐步进行:
首先,我们将dmax
设置为1.0。然后,如果distance>dmax
,dmax
设置为distance
。因此,dmax
不可能小于1.0
然后,如果dmax>epsilon
,我们递归。如果epsilon<1.0,则始终会发生这种情况
如果我们查看上的算法,您可以看到dmax
应该从0.0开始
顺便说一句,您可以使用该函数使距离函数变得更好。在本
dmax
中,从0
开始。为什么要用1.0
启动dmax
?一般来说,堆栈溢出是一种用户错误:)@MatthieuM。哦,我从来没有怀疑过这是真的。不幸的是,对于我来说,这并不是一个更微妙的错误……在这个dmax
中,它以0
开头。为什么要用1.0
启动dmax
?一般来说,堆栈溢出是一种用户错误:)@MatthieuM。哦,我从来没有怀疑过这是真的。不幸的是,对我来说,这并不是一个更微妙的错误……好吧,这很尴尬。好吧,这很尴尬。