快速确定数组中数据的位置

时间:2009-12-15 21:37:22

标签: actionscript-3 algorithm arrays data-structures loops

我有一个数据结构,如下图所示。我需要快速找出突出显示的单元格组右侧或左侧的单元格索引。

some data

你可以在下面的代码中看到我在每个索引处天真地循环遍历所有单元格,以确定在所请求的索引处是否有一个单元格。当我有几百个细胞时,这种方法很有效,但是当我有数千个细胞时会很快崩溃。

在这种特殊情况下,突出显示的组是移动的,并且只能在上一个/下一个被占用的单元之前或之后移动到索引。因此groupMinX / maxX是它可以根据行中其他单元格的位置移动的最小和最大x值。

            private var movingGroup:CellGroup; //selected group

    public function getCellAtIndex(index:int):ICell
    {
        for each(var cell:ICell in cells)
        {
            if(cell.index==index)
                return cell;
        }

        return null;
    }

    public function groupMinX(xPos:Number):Number
    {
        var index:int = xPos/cellSize;
        var cellsOnLeft:Array = getAllCellsOnLeft(index-1);
        if(cellsOnLeft.length > 0)
            return cellsOnLeft[cellsOnLeft.length-1].x + cellSize;
        return 0;
    }

    public function groupMaxX(xPos:Number):Number
    {
        var index:int = xPos/cellSize;
        var cellsOnRight:Array = getAllCellsOnRight(index);
        if(cellsOnRight.length > 0)
            return cellsOnRight[0].x;
        return (maxIndex)*cellSize;
    }

    private function getAllCellsOnLeft(ofIndex:int):Array
    {
        var index:int = 1;
        var cells:Array = [];
        while( ofIndex >= 0 )
        {
            var cell:ICell = getCellAtIndex(ofIndex);
            if(cell && !movingGroup.containsCell(cell))
                cells.unshift( cell );
            ofIndex--;
        }
        return cells;       
    }

    private function getAllCellsOnRight(ofIndex:int):Array
    {
        var index:int = 1;
        var cells:Array = [];
        while( index <= maxIndex )
        {
            var cell:ICell = getCellAtIndex( ofIndex + index );
            if(cell && !movingGroup.containsCell(cell))
                cells.push( cell );
            index++;
        }
        return cells;       
    }

我正在寻找的是一种扫描/跟踪细胞的有效方法。我循环的数组实际上并不包含空白单元格,但它具有索引属性的单元格。

4 个答案:

答案 0 :(得分:1)

在我的推文中哎呀我添加了错误的链接。使用链接列表。让'Cell'类实现Linked List Node接口。无需循环或使用条件。

http://en.wikipedia.org/wiki/Linked_list

答案 1 :(得分:1)

当列表被订购时,我建议你进行二元搜索以找到你想要的单元格。然后,不是将元素循环到左侧和右侧,而是简单地切割数组以形成左侧和右侧的两个新阵列。

这样的事情,不幸? (请原谅任何语法错误,我不知道动作...)

private function search(array:Array, index:int, low:int, high:int) :int 
{ 
  if (high < low)
    return -1 
  var middle:int = low + ((high - low) / 2) 
  if (array[middle].index > index)
    return search(array, index, low, middle - 1)
  else if (array[middle].index < index)
    return search(array, index, middle + 1, high)
  else
    return middle 
}  

private function sliceBitsOff(index:int)
{
   var index:int = search(yourArray, 7, 0, yourArray.length-1)
   var rightArray:Array = yourArray.slice(0, index - 1)
   var leftArray:Array = yourArray.slice(index + 1, yourArray.length)
}

答案 2 :(得分:0)

您可以预先缓存左侧单元格的索引和右侧单元格的索引... 您对数据结构的选择并不理想。请描述您在更高级别尝试做的事情。这个数据结构是给你的,还是你想出来的?

答案 3 :(得分:0)

我不确定我是否遗漏了一些东西,但如果这是一个数字索引的对象数组(单元格), 我想你可以做点像......

cellsArr[cellsArr.indexOf(cellObj1) - 1] // previous cell    
cellsArr[cellsArr.indexOf(cellObj2) + 1] // get the cell after a "highlighted" cell