Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.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
Arrays 带O(kn logn)的平衡K-D树算法_Arrays_Algorithm_Tree_Kdtree - Fatal编程技术网

Arrays 带O(kn logn)的平衡K-D树算法

Arrays 带O(kn logn)的平衡K-D树算法,arrays,algorithm,tree,kdtree,Arrays,Algorithm,Tree,Kdtree,我尝试用O(kn logn)实现一个平衡的K-D树,我使用预排序的K数组(每个索引的排序数组)得到O(kn logn),使用中值得到平衡树 我面临的问题是,在某些级别上,例如x轴的中值,可能会在另一个后续级别上再次选择,例如y轴 我试图通过使用所选的x值作为轴心将y排序的数组划分为两个数组来解决这个问题,但这种方法无法生成平衡树 知道如何用O(knlogn)得到K-D平衡树吗 编辑 引自维基 构建平衡k-d树的替代算法对 构建树之前的数据。然后他们就维持了秩序 在树施工期间进行预分类,从而消除

我尝试用O(kn logn)实现一个平衡的K-D树,我使用预排序的K数组(每个索引的排序数组)得到O(kn logn),使用中值得到平衡树

我面临的问题是,在某些级别上,例如x轴的中值,可能会在另一个后续级别上再次选择,例如y轴

我试图通过使用所选的x值作为轴心将y排序的数组划分为两个数组来解决这个问题,但这种方法无法生成平衡树

知道如何用O(knlogn)得到K-D平衡树吗

编辑

引自维基

构建平衡k-d树的替代算法对 构建树之前的数据。然后他们就维持了秩序 在树施工期间进行预分类,从而消除成本高昂的步骤 在每个细分级别查找中间值的步骤。两个这样的 算法建立一个平衡的k-d树对三角形进行排序,以便 提高三维场景光线跟踪的执行时间 计算机图形学。这些算法先对n个三角形进行预排序,然后再进行预排序 构建k-d树,然后在 最佳情况。[5][6]构建平衡k-d树进行排序的算法 点的最坏情况复杂度为O(kn log n)。[7]此算法 使用O(n logn)排序在k个维度中的每个维度中预排序n个点 例如,在构建树之前进行堆排序或合并排序。那么 在树构建和维护过程中保持这些k类的顺序 从而避免在每个细分级别上查找中间值

任何人都可以提供上述算法?

编辑

提出了一种方法,但如果中位数的特定轴存在任何重复值,则该方法无效

比如说

x1=[(0,7)、(1,3)、(3,0)、(3,1)、(6,2)]y1=[(3,0)、(3,1)、(6,2)、(1,3)、(0,7)]

x轴的中位数为3。 因此,当我们想要分割数组y11和y12时,我们必须使用>和<将y数组左右分布,并将轴作为分隔符

如果特定轴上的中间带a重复,则不能保证其中一个是正确的

考虑x轴上的分区,完成上述第一步分区示例后,x1阵列上没有问题:

median=(3,0)
The pivot = 3 // is it's the median of x axis
y11[],y12[] 
for(i = 0 ; i < x1.size;i++)
  if(y1[i].getX()<pivot)
    y11.add(y1[i])
  else 
    if(y1[i].getX()>pivot)
     y12.add(y1[i])
中值=(3,0)
轴=3//是x轴的中位数
y11[],y12[]
对于(i=0;i
这将导致y11=[(2,1)、(1,3)、(0,7)]y12=[(6,2)]

你知道如何处理这种情况吗? 或者是否有其他预排序kd树预排序算法O(kn log n)?

拆分数据时,需要保留排序顺序

例如,使用数据
(x,y)
我们构建

x1 = [ (0, 7), (1, 3), (3, 0), (4, 2), (6, 1) ]
y1 = [ (3, 0), (6, 1), (3, 2), (1, 3), (0, 7) ]
如果我们现在在x处拆分,我们需要通过
x=3,y=0处的记录过滤这两个集合

即拆分两个列表,删除
(3,0)
,所有带有
x3
的项目转到第二个(顺序不变):

关键是要用x值过滤每个排序列表,同时保持排序顺序(因此在每个O(logn)级别中都是O(n*k)。如果仅使用x1,并从x1重建y11和y12,则需要再次排序。根据需要,这与按x、y进行一次排序是一样的。除了我们没有再次排序,只选择了


我认为这在实践中没有多大好处。排序比额外内存便宜。

详细说明我的评论(可能还有):

在构造KD树时,预排序的关键思想是在分割过程中保持顺序。开销看起来相当高,重新排序(和k-select)的比较基准似乎是有序的。
一些Java源代码的原理证明:

package net.*.coder.greybeard.sandbox;

import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;

/** finger exercise pre-sorting & split for KD-tree construction
 *  (re. https://stackoverflow.com/q/35225509/3789665) */
public class KDPreSort {
 /** K-dimensional key, dimensions fixed
  *   by number of coordinates in construction */
    static class KKey {
        public static KKey[] NONE = {};
        final Comparable[]coordinates;
        public KKey(Comparable ...coordinates) {
            this.coordinates = coordinates;
        }
    /** @return {@code Comparator<KKey>} for coordinate {@code n}*/
        static Comparator<KKey> comparator(int n) { // could be cached
            return new Comparator<KDPreSort.KKey>() { @Override
                    public int compare(KKey l, KKey r) {
                        return l.coordinates[n]
                            .compareTo(r.coordinates[n]);
                    }
                };
        }
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder(
                Arrays.deepToString(coordinates));
            sb.setCharAt(0, '(');
            sb.setCharAt(sb.length()-1, ')');
            return sb.toString();
        }
    }

 // static boolean trimLists = true; // introduced when ArrayList was used in interface

/** @return two arrays of {@code KKey}s: comparing smaller than
 *    or equal to {@code pivot} (according to {@code comp)},
 *    and greater than pivot -
 *    in the same order as in {@code keys}. */
    static KKey[][] split(KKey[] keys, KKey pivot, Comparator<KKey> comp) {
        int length = keys.length;
        ArrayList<KKey>
            se = new ArrayList<>(length),
            g = new ArrayList<>(length);
        for (KKey k: keys) {
        // pick List to add to
            List<KKey>d = comp.compare(k, pivot) <= 0 ? se : g;
            d.add(k);
        }
//      if (trimLists) { se.trimToSize(); g.trimToSize(); }
        return new KKey[][] { se.toArray(KKey.NONE), g.toArray(KKey.NONE) };
    }
 /** @return two arrays of <em>k</em> arrays of {@code KKey}s:
  *  comparing smaller than or equal to {@code pivot}
  *   (according to {@code comp)}, and greater than pivot,
  *  in the same order as in {@code keysByCoordinate}. */
    static KKey[][][]
        splits(KKey[][] keysByCoordinate, KKey pivot, Comparator<KKey> comp) {
        final int length = keysByCoordinate.length;
        KKey[][]
            se = new KKey[length][],
            g = new KKey[length][],
            splits;
        for (int i = 0 ; i < length ; i++) {
            splits = split(keysByCoordinate[i], pivot, comp);
            se[i] = splits[0];
            g[i] = splits[1];
        }
        return new KKey[][][] { se, g };
    }
 // demo
    public static void main(String[] args) {
    // from https://stackoverflow.com/q/17021379/3789665
        Integer [][]coPairs = {// {0, 7}, {1, 3}, {3, 0}, {3, 1}, {6, 2},
                {12, 21}, {13, 27}, {19, 5}, {39, 5}, {49, 63}, {43, 45}, {41, 22}, {27, 7}, {20, 12}, {32, 11}, {24, 56},
            };
        KKey[] someKeys = new KKey[coPairs.length];
        for (int i = 0; i < coPairs.length; i++) {
            someKeys[i] = new KKey(coPairs[i]);
        }
    //presort
        Arrays.sort(someKeys, KKey.comparator(0));
        List<KKey> x = new ArrayList<>(Arrays.asList(someKeys));
        System.out.println("by x: " + x);
        KKey pivot = someKeys[someKeys.length/2];
        Arrays.sort(someKeys, KKey.comparator(1));
        System.out.println("by y: " + Arrays.deepToString(someKeys));
    // split by x
        KKey[][] allOrdered = new KKey[][] { x.toArray(KKey.NONE), someKeys },
            xSplits[] = splits(allOrdered, pivot, KKey.comparator(0));
        for (KKey[][] c: xSplits)
            System.out.println("split by x of " + pivot + ": "
                + Arrays.deepToString(c));
    // split "higher x" by y
        pivot = xSplits[1][1][xSplits[1][1].length/2];
        KKey[][] ySplits[] = splits(xSplits[1], pivot, KKey.comparator(1));
        for (KKey[][] c: ySplits)
            System.out.println("split by y of " + pivot + ": "
                + Arrays.deepToString(c));
    }
}
package net.*.coder.greybeard.sandbox;
导入java.util.array;
导入java.util.Comparator;
导入java.util.LinkedList;
/**用于KD树构建的手指练习预排序和拆分
*(关于。https://stackoverflow.com/q/35225509/3789665) */
公共类KDPreSort{
/**K维键,尺寸固定
*按构造中的坐标数*/
静态类KKey{
公共静态KKey[]无={};
最终可比[]坐标;
公共KKey(可比…坐标){
这个。坐标=坐标;
}
/**坐标{@code n}的@return{@code Comparator}*/
静态比较器比较器(int n){//可能被缓存
返回新的比较器(){@Override
公共整数比较(KKey l,KKey r){
返回l坐标[n]
.比较(r坐标[n]);
}
};
}
@凌驾
公共字符串toString(){
StringBuilder sb=新的StringBuilder(
数组。深度字符串(坐标);
sb.setCharAt(0,“(”);
sb.setCharAt(sb.length()-1');
使某人返回字符串();
}
}
//静态布尔trimLists=true;//在接口中使用ArrayList时引入
/**@return两个{@code KKey}数组:比较小于
*或等于{@code pivot}(根据{@code comp)},
*大于枢轴-
*与{@code key}中的顺序相同*/
静态KKey[][]分割(KKey[]键、KKey枢轴、比较器补偿){
int length=keys.length;
ArrayList
se=新阵列列表(长度),
g=新阵列列表(长度);
用于(KKey k:密钥){
//要添加到的拾取列表

Listd=comp.compare(k,pivot)这可能不会发生。在第一个细分步骤之后,左子树和右子树将分别处理,并且不包含初始中位数。除非您能够在不丢失
y
顺序的情况下,对
y
排序集进行分区,否则对
x
进行预排序是无用的。(请检查标记平衡。)
package net.*.coder.greybeard.sandbox;

import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;

/** finger exercise pre-sorting & split for KD-tree construction
 *  (re. https://stackoverflow.com/q/35225509/3789665) */
public class KDPreSort {
 /** K-dimensional key, dimensions fixed
  *   by number of coordinates in construction */
    static class KKey {
        public static KKey[] NONE = {};
        final Comparable[]coordinates;
        public KKey(Comparable ...coordinates) {
            this.coordinates = coordinates;
        }
    /** @return {@code Comparator<KKey>} for coordinate {@code n}*/
        static Comparator<KKey> comparator(int n) { // could be cached
            return new Comparator<KDPreSort.KKey>() { @Override
                    public int compare(KKey l, KKey r) {
                        return l.coordinates[n]
                            .compareTo(r.coordinates[n]);
                    }
                };
        }
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder(
                Arrays.deepToString(coordinates));
            sb.setCharAt(0, '(');
            sb.setCharAt(sb.length()-1, ')');
            return sb.toString();
        }
    }

 // static boolean trimLists = true; // introduced when ArrayList was used in interface

/** @return two arrays of {@code KKey}s: comparing smaller than
 *    or equal to {@code pivot} (according to {@code comp)},
 *    and greater than pivot -
 *    in the same order as in {@code keys}. */
    static KKey[][] split(KKey[] keys, KKey pivot, Comparator<KKey> comp) {
        int length = keys.length;
        ArrayList<KKey>
            se = new ArrayList<>(length),
            g = new ArrayList<>(length);
        for (KKey k: keys) {
        // pick List to add to
            List<KKey>d = comp.compare(k, pivot) <= 0 ? se : g;
            d.add(k);
        }
//      if (trimLists) { se.trimToSize(); g.trimToSize(); }
        return new KKey[][] { se.toArray(KKey.NONE), g.toArray(KKey.NONE) };
    }
 /** @return two arrays of <em>k</em> arrays of {@code KKey}s:
  *  comparing smaller than or equal to {@code pivot}
  *   (according to {@code comp)}, and greater than pivot,
  *  in the same order as in {@code keysByCoordinate}. */
    static KKey[][][]
        splits(KKey[][] keysByCoordinate, KKey pivot, Comparator<KKey> comp) {
        final int length = keysByCoordinate.length;
        KKey[][]
            se = new KKey[length][],
            g = new KKey[length][],
            splits;
        for (int i = 0 ; i < length ; i++) {
            splits = split(keysByCoordinate[i], pivot, comp);
            se[i] = splits[0];
            g[i] = splits[1];
        }
        return new KKey[][][] { se, g };
    }
 // demo
    public static void main(String[] args) {
    // from https://stackoverflow.com/q/17021379/3789665
        Integer [][]coPairs = {// {0, 7}, {1, 3}, {3, 0}, {3, 1}, {6, 2},
                {12, 21}, {13, 27}, {19, 5}, {39, 5}, {49, 63}, {43, 45}, {41, 22}, {27, 7}, {20, 12}, {32, 11}, {24, 56},
            };
        KKey[] someKeys = new KKey[coPairs.length];
        for (int i = 0; i < coPairs.length; i++) {
            someKeys[i] = new KKey(coPairs[i]);
        }
    //presort
        Arrays.sort(someKeys, KKey.comparator(0));
        List<KKey> x = new ArrayList<>(Arrays.asList(someKeys));
        System.out.println("by x: " + x);
        KKey pivot = someKeys[someKeys.length/2];
        Arrays.sort(someKeys, KKey.comparator(1));
        System.out.println("by y: " + Arrays.deepToString(someKeys));
    // split by x
        KKey[][] allOrdered = new KKey[][] { x.toArray(KKey.NONE), someKeys },
            xSplits[] = splits(allOrdered, pivot, KKey.comparator(0));
        for (KKey[][] c: xSplits)
            System.out.println("split by x of " + pivot + ": "
                + Arrays.deepToString(c));
    // split "higher x" by y
        pivot = xSplits[1][1][xSplits[1][1].length/2];
        KKey[][] ySplits[] = splits(xSplits[1], pivot, KKey.comparator(1));
        for (KKey[][] c: ySplits)
            System.out.println("split by y of " + pivot + ": "
                + Arrays.deepToString(c));
    }
}