我有一个RedBlack [Balanced,sorted]二进制树,我正在搜索它以查找[lower,upper]范围内的所有值。
public IEnumerable<TData> Range(
BinaryTree<TData> root,
IComparer<TData> comparer,
TData lower,
TData upper)
{
var stack = new Stack<State>(16);
BinaryTree<TData> here = root;
do
{
if (here == null)
{
if (stack.Count == 0)
break;
State popped = stack.Pop();
yield return popped.Data;
here = popped.Next;
continue;
}
if (comparer.Compare(here.Data, lower) < 0)
{
here = here.Right;
}
else if (comparer.Compare(here.Data, upper) > 0)
{
here = here.Left;
}
else
{
stack.Push(new State {Next = here.Right, Data = here.Data});
here = here.Left;
}
} while (true);
}
因此,使用此代码,如果我要使用值
构建树 [0, 1, 4, 5, 6, 9],
并搜索范围内的所有元素
[3, 8]
我会得到以下结果:
[4, 5, 6].
我的问题是如何调整此算法以获取搜索的外部元素?像这样:
[1, 4, 5, 6, 9]
即。值3位于树中的1和4之间,所以我想返回1,类似地,值8位于6和9之间,我希望值9包含在结果中。
一个问题是我不想从root重启搜索
目前使用NGenerics
实施[编辑]
愿意接受一般的算法答案。
答案 0 :(得分:0)
我不确定你想要填充红黑树的内容。但是如果你使用数组或数据流(其元素数量不会改变),你可以使用Segment Tree
class SegmentTree
{
class Node
{
int max, min, s, e;
Node left, right;
@Override
public String toString()
{
String str = "Min: "+this.min+" Max: "+this.max+" "+this.s+"-"+this.e;
return str;
}
}
private Node root;
public SegmentTree() {}
public SegmentTree(int[] array)
{
add(array);
}
public void add(int[] array)
{
root = add(0, array.length-1, array);
}
private Node add(int s, int e, int[] array)
{
Node n = new Node();
n.s = s;
n.e = e;
if(n.s==n.e)
{
n.min = n.max = array[n.s];
return n;
}
int mid = s+(e-s)/2;
n.left = add(s, mid, array);
n.right = add(mid+1, e, array);
n.max = Math.max(n.left.max, n.right.max);
n.min = Math.min(n.left.min, n.right.min);
return n;
}
// Get the max value between the limits l and r (both inclusive)
public int getMax(int l, int r)
{
return getMax(root, l, r);
}
private int getMax(Node n, int l, int r)
{
if(l<=n.s && r>=n.e)
return n.max;
if(l>n.e || r<n.s)
return Integer.MIN_VALUE;
return Math.max(getMax(n.left, l, r), getMax(n.right, l, r));
}
public int getMin(int l, int r)
{
return getMin(root, l, r);
}
private int getMin(Node n, int l, int r)
{
if(l<=n.s && r>=n.e)
return n.min;
if(l>n.e || r<n.s)
return Integer.MAX_VALUE;
return Math.min(getMin(n.left, l, r), getMin(n.right, l, r));
}
}
注意
如果数据有增加或减少,则必须重建树。如果频繁插入/删除/更新,那么这根本不是一个好的选择
当您拥有一组数据并且需要经常检查特定范围的值时,这非常有用
我给出了存储最小值和最大值的示例。您可以在Node
中存储值或其他任何内容的总和
为在JAVA中编写代码道歉:)