2

上个月我一直在制作一个照片马赛克网站。我用 PHP 构建了所有东西,我让它工作得很好。我唯一不喜欢的是执行时间。由于线性比较搜索,我认为这太长了。所以我一直在询问如何改善我的搜索时间,大多数人都将我指向 KD-tree 的方向,这将使 k-最近邻变得更快。

所以我一直在研究 KD-tree 并且我了解如何手动构建这样的树。现在我当然想编写这个代码,我只能找到 C++ 和 java 的库。因为我只熟悉 PHP,所以我一直在尝试自己制作,但这并不像我想象的那么容易。

• 我面临的一个问题是如何存储所有内容。当我得到第一个包含所有点的数组时,我会将它分成 3 块。左分支、节点和右分支。当然我会对左分支做同样的事情,直到我不能再分裂,当然我循环穿过轴(XYZ)。但是我如何存储所有正确的分支,我将它们留在数组中吗?还是在我准备好使用它们时再次计算它们?

• 我想知道的另一件事是为什么没有 PHP KD-tree 脚本是因为 PHP 不是适合这项工作的语言?

这就是我到目前为止所得到的。

这个函数计算我用来测试其余部分的随机颜色 (RGB)。

<?php
function randomiser($number){

    if($number <= 0){ 
        echo 'Error: The input of randomiser() is less than or equal to zero !!';
        return FALSE;         
    }else{ 
        $R = array();
        $G = array();
        $B = array();

        for($x = 1; $x <= $number; $x++){
            $r = rand(1, 255);
            $g = rand(1, 255);
            $b = rand(1, 255);

            $rgb['pic ' . $x]['R'] = $r;
            $rgb['pic ' . $x]['G'] = $g;
            $rgb['pic ' . $x]['B'] = $b;    
        }  
    }
return $rgb;
}
?>

此函数对特定键上的多维数组进行排序(默认为 R)

<?php
function sorter(&$array, $key = 'R'){

    if(!is_array($array)){ 
        echo 'Error: The input of sorter() is not an array !!<br>';
        return FALSE;         
    }else{ 
        uasort($array, function ($a, $b) use ($key){
            return strnatcmp($a[$key], $b[$key]);
        }); 
    }
}
?>

此类将数组拆分为左分支、节点和右分支。

<?php
class splitting {

    public $left;
    public $node;
    public $right;

    function __construct($array){

        if(!is_array($array)){ 
            echo 'Error: The input of splitter() is not an array !!<br>';
            return FALSE;         
        }else{ 
            $number = count($array);
            $median = round($number / 2) - 1; 

            $this->left = array_slice($array, 0, $median);
            $this->node = array_slice($array, $median, 1);
            $this->right = array_slice($array, $median+1);
        }
    }
}
?>
4

1 回答 1

0
  1. 您需要将指向树的指针存储在 $left 和 $right 变量中,而不是数组或您需要使用的任何变量。如果 kd-tree 太复杂,我也会研究 r-tree。r-tree 将平面分成 4 个边,即在真正的 2 euklidian 维度中,kd-tree 只是一个二叉树。然后你需要一个变量 $payload 或其他东西来备份中位数。
  2. 不,您还可以找到 php 树示例。这是一个示例:http: //blog.sandfox.co.uk/2012/09/10/php-kdtree/。您还可以在 php 中查找我的 kart-trie 实现。它还使用 OO 以及节点和边类。这是一个从http://www.blackpawn.com/texts/lightmaps/default.html将光照贴图打包到 kd 树中的脚本。

     struct Node
    {
         Node* child[2]
         Rectangle rc
          int imageID
     }
    
    Node* Node::Insert(const Image& img)
          if we're not a leaf then
          (try inserting into first child)
           newNode = child[0]->Insert( img )
          if newNode != NULL return newNode
    
     (no room, insert into second)
          return child[1]->Insert( img )
      else
    (if there's already a lightmap here, return)
    if imageID != NULL return NULL
    
    (if we're too small, return)
    if img doesn't fit in pnode->rect
        return NULL
    
    (if we're just right, accept)
    if img fits perfectly in pnode->rect
        return pnode
    
    (otherwise, gotta split this node and create some kids)
    pnode->child[0] = new Node
    pnode->child[1] = new Node
    
    (decide which way to split)
    dw = rc.width - img.width
    dh = rc.height - img.height
    
    if dw > dh then
        child[0]->rect = Rectangle(rc.left, rc.top, 
                                   rc.left+width-1, rc.bottom)
        child[1]->rect = Rectangle(rc.left+width, rc.top, 
                                   rc.right, rc.bottom)
    else
        child[0]->rect = Rectangle(rc.left, rc.top, 
                                   rc.right, rc.top+height-1)
        child[1]->rect = Rectangle(rc.left, rc.top+height, 
                                   rc.right, rc.bottom)
    
    (insert into first child we created)
    return Insert( img, pnode->child[0] )
    
于 2012-12-18T12:17:01.740 回答