如何解决字典排序自定义关键字查找以提高效率
最近,我了解到Sorted Dictionary类在键上实现了二进制搜索,我想以此为自己的优势。我正在制作一个piecewise线性函数类,它表示一系列间隔上的线集合。
我这样定义了Interval
类:
public class Interval : ICloneable,IComparable,IComparable<Interval>
{
public Interval()
{
}
public Interval(double start,double end)
{
Start = start;
End = end;
}
// Properties
public double Start { get; set; } = double.NaN;
public double End { get; set; } = double.NaN;
public double Span => End - Start;
// Methods
public object Clone() => MemberwiseClone();
public int CompareTo(object obj)
{
return Start.CompareTo(obj);
}
public int CompareTo([AllowNull] Interval other)
{
if (Start < other.Start)
{
return -1;
}
else if (Start > other.Start)
{
return 1;
}
else
{
return 0;
}
}
public bool Contains(double x) => Start <= x && x <= End;
public override string ToString() => $"[{Start},{End}]";
}
有问题的SortedDictionary
在分段函数类中的工作方式如下:
public class PiecewiseLinearFunction : ICloneable
{
...
// The dictionary
public SortedDictionary<Interval,Line2D> Functions { get; set; } = new SortedDictionary<Interval,Line2D>(); // Where Line2D is just a class that contains a function definition for a line
// Methods
public Interval FindInterval(double x)
=> Functions.Keys.Where(interval => interval.Contains(x)).FirstOrDefault();
public double Solve(double x)
{
var interval = FindInterval(x);
if (interval != null && Functions.ContainsKey(interval))
{
return Functions[interval].Solve(x);
}
else
{
return double.NaN;
}
}
}
如您所见,PiecewiseLinearFunction.FindInterval(double x)
方法线性搜索字典的键,以查找包含(或不包含)x
的间隔,该间隔可用于二进制外观-up,但这显然会破坏进行二进制查找的目的。
我想知道是否可以以某种方式使字典查找double x
值,并在检查Interval.Contains(double x)
是true
还是{{1 }}来确定是否存在有效的间隔(键)和相应的行,这些行可用于获取false
处的函数值。
换句话说,有没有一种方法可以搜索谓词,例如x
。
解决方法
因此,如果间隔不重叠,则实际上实际上不需要自定义二进制搜索。
首先,如果我们使Interval
与double
具有可比性,那么它会有所帮助:
public class Interval: IComparable<double>
{
public double Start { get; set; }
public double End { get; set; }
public bool Contains(double x) => x >= Start && x <= End;
public int CompareTo(double other)
{
if (Contains(other))
return 0;
return other < Start ? 1 : -1;
}
}
现在,我们创建一个List
扩展名,以便能够使用其他类型(仅列表类型)进行二进制搜索:
public static class ListExtensions
{
public static int BinarySearch<T,TU>(this List<T> sortedSource,TU val) where T : IComparable<TU>
{
return sortedSource.BinarySearch(default(T),Comparer<T>.Create((item,_) => item.CompareTo(val)));
}
}
现在我们可以像这样测试它了:
var list = new List<Interval>
{
new Interval
{
Start = 0,End = 4
},new Interval
{
Start = 6,End = 7
},new Interval
{
Start = 10,End = 12
}
};
var index = list.BinarySearch(6.0d); //index = 1
var interval = index < 0 ? null : list[index]; //interval = [6,7]
index = list.BinarySearch(9.0d); //index = -3
interval = index < 0 ? null : list[index]; //interval = null
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。