在构造kd树时,对“中位数”的定义感到困惑

时间:2010-05-28 06:58:42

标签: c++ median kdtree

我正在尝试构建一个用于搜索一组点的kd树,但我对在维基百科文章中使用“中位数”感到困惑。为了便于使用,维基百科文章将kd-tree构造的伪代码声明为:

function kdtree (list of points pointList, int depth)
{
    if pointList is empty
        return nil;
    else
    {
        // Select axis based on depth so that axis cycles through all valid values
        var int axis := depth mod k;

        // Sort point list and choose median as pivot element
        select median by axis from pointList;

        // Create node and construct subtrees
        var tree_node node;
        node.location := median;
        node.leftChild := kdtree(points in pointList before median, depth+1);
        node.rightChild := kdtree(points in pointList after median, depth+1);
        return node;
    }
}

我对“选择中位数......”这一行感到困惑,原因很简单,因为我不太清楚这里应用中位数的“正确”方法是什么。

据我所知,奇数(排序)数字列表的中位数是中间元素(也就是说,对于标准的从零开始的数组中的5个事物,元素编号3或索引2的列表),偶数大小的数组的中位数是两个“中间”元素除以2的总和(也就是说,对于6个事物的列表,中位数是元素3和4的总和 - 或者2和3,如果零索引 - 除以2。)。

然而,由于我们正在使用一组不同的点,因此这个定义肯定不起作用?那么如何为偶数大小的数字列表选择正确的中位数,尤其是长度为2的列表?

感谢所有人的帮助,谢谢!

-Stephen

2 个答案:

答案 0 :(得分:3)

在我看来,你理解中位数的含义,但你却对其他东西感到困惑。你的意思是什么是不同的点?

维基百科提供的代码是递归函数。您有一组点,因此您创建根节点并选择集合的中位数。然后以递归方式调用函数 - 对于左子树,您传入一个参数,其中所有点都小于原始列表的分割值(中位数),对于您在相等和较大的子树中传递的右子树。然后,对于每个子树,创建一个节点,其中发生相同的事情。它是这样的:

First step (root node):
Original set: 1 2 3 4 5 6 7 8 9 10
Split value (median): 5.5

Second step - left subtree:
Set: 1 2 3 4 5
Split value (median): 3

Second step - right subtree:
Set: 6 7 8 9 10
Split value (median): 8

Third step - left subtree of left subtree:
Set: 1 2
Split value (median): 1.5

Third step - right subtree of left subtree:
Set: 3 4 5
Split value (median): 4

因此,基于进入该子树的数字集(点,数据),为树中的每个节点选择中值。希望这会有所帮助。

答案 1 :(得分:0)

您必须选择一侧具有与另一侧相同数量的元素的轴。如果点的数量是奇数,或者点的位置是不可能的,那么只需选择一个轴以尽可能均匀地重新分配。