KDtree(范围搜索)(DSL_2_C:Range Search)

对于某个二维平面上的点的集合,列举出给定范围内的点。

首先将问题简化:把点集合从二维空间缩小到一维的x轴上,考虑如何列举出x轴上给定区域(范围)内的点,即一维的范围搜索

np=0;
make1dtree(0,n);

make1dtree(l,r)
{
    if(!(l>1;
    T=np++;
    t[T].location=mid;
    t[T].l=make1dtree(l,mid);
    t[T].r=make1dtree(mid+1,r);
    return T;
}

列举出指定范围内的点

find(v,sx,tx)
{
    x=p[t[v].location].x;
    if(sx<=x&&x<=tx){
        print(p[v].location);
    }
    if(t[v].l!=NIL&&sx<=x){
        find(t[v].l,sx,tx);
    }
    if(t[v].r!=NIL&&x<=tx){
        find(t[v].r,sx,tx);
    }
}

算法进行拓展至K维空间,需要构建名为“KD树”的数据结构,就可以搜索指定区域内的点了。

KD树的生成方法多种多样,针对二维平面的基本方法:K维算法的基本思路与一维算法的一样,都是需要对点进行排序,然后取中间值作为根节点来构建树。

前面处理一维(x轴上的点)问题时,只以x的值为基准进行了排序,但是点分布到二维空间后,我们就需要对x轴和y轴分别排序,至于要选择哪个轴为基准,则是按照树的深度进行循环,比如深度为偶数时以 x轴为基准,为奇数时以y轴为基准,二者交替出现。

make2d(l,r,depth)
{
    if(!(l>1;
    T=np++;
    if(depth%2==0){
        以x坐标为基准,将p从l到r的点进行升序排列
    }else{
        以y坐标为基准,将p从l到r的点进行升序排列
    }
    t[T].location=mid;
    t[T].l=make2dtree(l,mid,depth+1);
    t[T].r=make2dtree(mid+1,r,depth+1);
    return T;
}

make2dtree是make1dtree的拓展,在访问结点时多检查了结点的深度depth,跟据深度的奇偶来变更排序基准(x,y轴),find函数也跟据depth来区分两种情况进行搜索。

复杂度:算法在构建树结构时需要进行logn(树的高)次o(logn)的排序,因此复杂度为o(logn)^2.

//KDtree
#include

using namespace std;

const int maxn=1e7+10;
const int NIL=-1;

struct node{
    int location,l,r;
};

struct point{
    int id,x,y;
    friend bool operator <(const point &a,const point &b){
        return a.id>1;
    int T=np++;
    if(depth%2==0){
        sort(p+l,p+r,lessx);
    }else{
        sort(p+l,p+r,lessy);
    }
    t[T].location=mid;
    t[T].l=makekdtree(l,mid,depth+1);
    t[T].r=makekdtree(mid+1,r,depth+1);
    return T;
}

void find(int v,int sx,int tx,int sy,int ty,int depth,vector&ans)
{
    int x=p[t[v].location].x;
    int y=p[t[v].location].y;
    if(sx<=x&&x<=tx&&sy<=y&&y<=ty){
        ans.push_back(p[t[v].location]);
    }
    if(depth%2==0){
        if(t[v].l!=NIL){
            if(sx<=x){
                find(t[v].l,sx,tx,sy,ty,depth+1,ans);
            }
        }
        if(t[v].r!=NIL){
            if(x<=tx){
                find(t[v].r,sx,tx,sy,ty,depth+1,ans);
            }
        }
    }else{
        if(t[v].l!=NIL){
            if(sy<=y){
                find(t[v].l,sx,tx,sy,ty,depth+1,ans);
            }
        }
        if(t[v].r!=NIL){
            if(y<=ty){
                find(t[v].r,sx,tx,sy,ty,depth+1,ans);
            }
        }
    }
}

int main()
{
    int x,y;
    scanf("%d",&n);
    for(int i=0;ians;
    for(int i=0;i


你可能感兴趣的:(KDtree)