예제 #1
0
        /// <summary>
        ///   Creates the Root node for a new <see cref="KDTree{T}"/> given
        ///   a set of data points and their respective stored values.
        /// </summary>
        ///
        /// <param name="points">The data points to be inserted in the tree.</param>
        /// <param name="leaves">Return the number of leaves in the Root subtree.</param>
        /// <param name="inPlace">Whether the given <paramref name="points"/> vector
        ///   can be ordered in place. Passing true will change the original order of
        ///   the vector. If set to false, all operations will be performed on an extra
        ///   copy of the vector.</param>
        ///
        /// <returns>The Root node for a new <see cref="KDTree{T}"/>
        ///   contained the given <paramref name="points"/>.</returns>
        ///
        protected static KDTreeNode <T> CreateRoot(double[][] points, bool inPlace, out int leaves)
        {
            // Initial argument checks for creating the tree
            if (points == null)
            {
                throw new ArgumentNullException("points");
            }

            if (!inPlace)
            {
                points = (double[][])points.Clone();
            }

            leaves = 0;

            int dimensions = points[0].Length;

            // Create a comparer to compare individual array
            // elements at specified positions when sorting
            ElementComparer <double> comparer = new ElementComparer <double>();

            // Call the recursive algorithm to operate on the whole array (from 0 to points.Length)
            KDTreeNode <T> Root = create(points, 0, dimensions, 0, points.Length, comparer, ref leaves);

            // Create and return the newly formed tree
            return(Root);
        }
예제 #2
0
        private static KDTreeNode <T> create(double[][] points,
                                             int depth, int k, int start, int length, ElementComparer <double> comparer, ref int leaves)
        {
            if (length <= 0)
            {
                return(null);
            }

            // We will be doing sorting in place
            int axis = comparer.Index = depth % k;

            Array.Sort(points, start, length, comparer);

            // Middle of the input section
            int half = start + length / 2;

            // Start and end of the left branch
            int leftStart  = start;
            int leftLength = half - start;

            // Start and end of the right branch
            int rightStart  = half + 1;
            int rightLength = length - length / 2 - 1;

            // The median will be located halfway in the sorted array
            var median = points[half];

            depth++;

            // Continue with the recursion, passing the appropriate left and right array sections
            var left  = create(points, depth, k, leftStart, leftLength, comparer, ref leaves);
            var right = create(points, depth, k, rightStart, rightLength, comparer, ref leaves);

            if (left == null && right == null)
            {
                leaves++;
            }

            // Backtrack and create
            return(new KDTreeNode <T>()
            {
                Axis = axis,
                Position = median,
                Left = left,
                Right = right,
            });
        }