代码之家  ›  专栏  ›  技术社区  ›  Tmdean

在子对象之前排序父对象的算法

  •  1
  • Tmdean  · 技术社区  · 15 年前

    我正在编写一个绘图应用程序,其中包括可以有孩子的形状。当我需要重新绘制画布时,我想对要绘制的形状进行排序,以便父母出现在他们的孩子面前。这样,父图形就不会绘制在子图形的顶部。下面是相关函数(用JavaScript编写)。前缀为的变量 my. 是实例变量。 my.draw_order 是需要重新绘制的形状索引数组(由下面的代码填充), my.ctx my.shapes 是按任意顺序排列的形状数组, my.update_rects

    redraw = function () {
        var i, shape_count, shape;
    
        shape_count = 0;
        for (i = 0; i < my.shapes.length; i++) {
            shape = my.shapes[i];
    
            if (shape.visible && shape.dirty) {
                my.draw_order[shape_count] = i;
                shape_count++;
            }
        }
    
        my.draw_order.length = shape_count;
    
        // sort shapes to draw so that parents appear before children ???
        my.draw_order.sort(shape_sort);
    
        for (i = 0; i < my.draw_order.length; i++) {
            shape = my.shapes[my.draw_order[i]];
    
            shape.draw(my.ctx, my.update_rects);
            shape.dirty = false;
        }
    
        my.update_rects.length = 0;
    };
    

    我的问题是:实现代码引用的shape_排序的最佳方法是什么?这是一个经常调用的例程,因此效率可能是一个问题。每个形状都有一个父属性,该属性包含对其父形状的引用。欢迎对更好的设计提出建议。维护 按排序顺序排列是不可取的选项。

    2 回复  |  直到 15 年前
        1
  •  3
  •   Miguel Ventura    15 年前

    如果您需要比树更复杂的数据结构,您应该检查 Topological Sort 算法。

        2
  •  2
  •   Gabe Moothart    15 年前

    我会保持树的形状。创建一个根目录(代表整个屏幕),并为父目录提供指向其子目录的指针。然后对树进行一次简单的前序遍历就足够了。

    要按照现有设计实现,您不需要放弃 my.shapes 大堆只需添加一个 my.root

    function preorder_draw(root) {
    
        //do stuff with root
        draw(root);
    
        for (child in root.children) {
            preorder_draw(child);
        }
    
    }