Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# b-树的绘制算法_C#_Algorithm_System.drawing_B Tree - Fatal编程技术网

C# b-树的绘制算法

C# b-树的绘制算法,c#,algorithm,system.drawing,b-tree,C#,Algorithm,System.drawing,B Tree,我在寻找一种算法,在WinForms的C#中为用户控件绘制b树。我想知道是否有一些简单的算法可以用来在链接节点之间画线,因为这是我的主要问题。对于绘图节点,我使用了Knuth算法,因为它很简单,只需要一次顺序遍历,而且我只需要一次遍历。我非常感谢您提供的任何资源,因为我只找到了一个可以遍历两次并且需要对node类进行大量修改的资源,我希望避免这种情况 我发现(上面提到的)唯一一件事是,但这根本不能说服我 我已经有了顺序遍历算法: public void Traverse(BTree<TKe

我在寻找一种算法,在WinForms的C#中为用户控件绘制b树。我想知道是否有一些简单的算法可以用来在链接节点之间画线,因为这是我的主要问题。对于绘图节点,我使用了Knuth算法,因为它很简单,只需要一次顺序遍历,而且我只需要一次遍历。我非常感谢您提供的任何资源,因为我只找到了一个可以遍历两次并且需要对node类进行大量修改的资源,我希望避免这种情况

我发现(上面提到的)唯一一件事是,但这根本不能说服我

我已经有了顺序遍历算法:

public void Traverse(BTree<TKey, TValue>.TraverseFunction function, ref int depth, ref int xPos)
    {
        depth++;

        int i = 0;
        for (i = 0; i < elements.Count; i++)
        {
            if (!isLeaf)
                children[i].Traverse(function, ref depth, ref xPos);

            function.Invoke(elements[i].Key, elements[i].Value, ref depth, ref xPos);
            xPos++;
        }

        if (!isLeaf)
            children[children.Count - 1].Traverse(function, ref depth, ref xPos);

        depth--;
    }
它(在绘制事件中)传递给树遍历方法,该方法调用根上的第一个方法

问题在于绘制链接节点(实际上是关键点)之间的线

我可以使用全局变量(控制范围)。我希望避免多次迭代并在另一个类中存储点节点,但如果这不可能,我将“去”它

@编辑

我决定从这里开始使用算法:

(最下面的一个)我想不出来,我试着把它转换成C,但我在

vol = vol.left()
vor = vor.right()
由于没有解释Left()和Right()的作用,我认为它们返回最近的Left()和Right()同级,但我认为可能不是这样,因为它在不应该返回的时候给我null(从而退出应用程序)

@编辑2

我把它整理好了,left()基本上就是L中的nextLeft()

def nextleft(tree):
if tree.thread:   return tree.thread
if tree.children: return tree.children[0]
else:             return None

尽管实现了这个算法,我还是希望得到任何“更快”的算法,因为我并不真正需要那个复杂的算法,而且它也不会显示键,只显示节点。

用函数编程术语来说,你必须折叠树:将前一个节点的结果作为处理输入的一部分来处理每个节点

因此,尝试在遍历父节点时将其位置传递给其子节点。这允许您从子节点绘制到父节点的线,而无需遍历两次

我将
Traverse()
更改为接受
Func

public void Traverse<TResult>(
    Func<KeyValuePair<TKey, TValue>, TResult, int, int, TResult> traverser, 
    TResult parentResult,
    ref int depth, 
    ref int xPos)
{
    depth++;

    int i = 0;
    for (i = 0; i < elements.Count; i++)
    {
        // Traverse this node first.
        var traverseResult = traverser.Invoke(elements[i], parentResult, depth, xPos);

        // Now traverse children and pass result of own traversal.
        if (!isLeaf)
            children[i].Traverse(traverser, traverseResult, ref depth, ref xPos);

        xPos++;
    }

    if (!isLeaf)
        children[children.Count - 1].Traverse(function, traverseResult, ref depth, ref xPos);

    depth--;
}

向我们展示您迄今为止所做的尝试。@ChristianKiewiet添加了代码。但这不会起作用:(因为这是一个按序遍历,它应该“保持”从左到右的顺序,使用遍历方法,我们在子元素之前打印元素(应该在子元素之前处理),这会打破顺序!这就是问题所在。.我们不知道“父元素”在遍历子对象之前,先定位-我认为这需要两次遍历,无论我们如何尝试这样做。@user1970395,那么您将节点位置的计算拆分为两个遍历器函数并将节点向上绘制成两个遍历器函数如何?
traverse()
然后将接受一个
Func
来计算位置,在子处理之前执行,一个
操作
来绘制节点,在子处理之后执行。我决定采用另一种方式,从我发布的链接()中实现算法作为一个单独的类,这样我就有一个遍历,它符合我的标准(某种程度上),我只需要处理它来显示键而不是节点。谢谢你的帮助!现在我将坚持这个算法,但如果我不能修改它以完全支持我需要的,我会回到你的想法。
public void Traverse<TResult>(
    Func<KeyValuePair<TKey, TValue>, TResult, int, int, TResult> traverser, 
    TResult parentResult,
    ref int depth, 
    ref int xPos)
{
    depth++;

    int i = 0;
    for (i = 0; i < elements.Count; i++)
    {
        // Traverse this node first.
        var traverseResult = traverser.Invoke(elements[i], parentResult, depth, xPos);

        // Now traverse children and pass result of own traversal.
        if (!isLeaf)
            children[i].Traverse(traverser, traverseResult, ref depth, ref xPos);

        xPos++;
    }

    if (!isLeaf)
        children[children.Count - 1].Traverse(function, traverseResult, ref depth, ref xPos);

    depth--;
}
private Point traverseFunction(KeyValuePair<TKey, TValue> element, Point parentPosition, int depth, int xPos)
{
    float x, y;

    x = xPos * (horizontalSpacing + horizontalSize);
    y = depth * (verticalSpacing + verticalSize);

    RectangleF rect = new RectangleF(x, y, horizontalSize, verticalSize);

    if(g.VisibleClipBounds.IntersectsWith(rect))
    {
        if(depth != treeHeight)
        {
            g.FillRectangle(Brushes.Black, x, y, horizontalSize, verticalSize);
            g.DrawString(element.Key.ToString(), SystemFonts.DefaultFont, Brushes.Gold, x + 2, y + 2);
        }
        else
        {
            g.FillRectangle(Brushes.Red, x, y, horizontalSize, verticalSize);
            g.DrawString(element.Key.ToString(), SystemFonts.DefaultFont, Brushes.White, x + 2, y + 2);
        }

        // Use the parent node's position to draw a line.
        g.DrawLine(new Pen(Color.Black, 3), parentPosition, new Point(x, y));
    }

    Console.WriteLine(key + " : " + depth);
    return new Point(x, y);
}