二维K-D树的构造及搜索

   K-D(K-Dimensional)树在很多聚类算法中都有应用,例如CURE算法。K-D树的构造说明请参考 J_Outsider的博文,本文这里只给出其构造代码如下:
主程序代码:
clc;
clear;
%读取数据文件,生成点矩阵
fileID = fopen('D:\matlabFile\K-D tree\test.txt');
C=textscan(fileID,'%f %f');
fclose(fileID);
%构造数据集,第一列为x轴,第二列为y轴
D=cat(2,C{1},C{2});
%保存构造结果
KD_Tree=CreateKD_Tree(D);
%节点中包含有分割域的构造结果
KD_Tree_Dim=CreateKD_Tree_Dim(D);
%测试点
point=[5.1 4.1];
%搜索邻近点
R=KD_Tree_Search(KD_Tree_Dim,point);

树的构造函数:CreateKD_Tree

function KDTree=CreateKD_Tree(D)
%计算两个维度上的数据方差,然后比较两个维度的方差,确定分割的维度,1代表x轴,2代表y轴
dimension=1;
if var(D(:,1))<=var(D(:,2))  
    dimension=2;
end
%取出分割域
col=sort(D(:,dimension));
index=ceil(length(col)/2);
%确定分裂点
split=col(index,1);
%对数据分组
node=[]; %结点
left_data=[]; %左枝数据集
right_data=[];%右枝数据集
for i=1:size(D,1)
    if (D(i,dimension)<split)       
       left_data=cat(1,left_data,D(i,:));       
    elseif(D(i,dimension)>split)        
        right_data=cat(1,right_data,D(i,:));        
    else
        node=D(i,:);
    end            
end
%向下遍历左结点
if isempty(left_data)
    left_node=[];
elseif size(left_data,1)==1
    left_node=left_data;
else
    left_node=CreateKD_Tree(left_data);
end
%向下遍历右结点
if isempty(right_data)
    right_node=[];
elseif size(right_data,1)==1
    right_node=right_data;
else
    right_node=CreateKD_Tree(right_data);
end

%将左右结点的结果加入树中
KDTree={node,left_node,right_node};

包含分割域的构造函数CreateKD_Tree_Dim

 %结点中包含分割域,例如结点[4 5 1],最后一位1代表分割域,目的是为了后续搜索K-D树:

function KDTree=CreateKD_Tree_Dim(D)  %结点中包含分割域,如如[4 5 1],最后一位1代表分割域,目的是为了方便搜索
%计算两个维度上的数据方差,然后比较两个维度的方差,确定分割的维度,1代表x轴,2代表y轴
dimension=1;
if var(D(:,1))<=var(D(:,2))  
    dimension=2;
end
%取出分割域
col=sort(D(:,dimension));
index=ceil(length(col)/2);
%确定分裂点
split=col(index,1);
%对数据分组
node=[]; %结点
left_data=[]; %左枝数据集
right_data=[];%右枝数据集
for i=1:size(D,1)
    if (D(i,dimension)<split)       
       left_data=cat(1,left_data,D(i,:));       
    elseif(D(i,dimension)>split)        
        right_data=cat(1,right_data,D(i,:));        
    else
        node=D(i,:);
    end            
end
%向下遍历左结点
if isempty(left_data)
    left_node=[];
elseif size(left_data,1)==1
    left_node=left_data;
else
    left_node=CreateKD_Tree_Dim(left_data);
end
%向下遍历右结点
if isempty(right_data)
    right_node=[];
elseif size(right_data,1)==1
    right_node=right_data;
else
    right_node=CreateKD_Tree_Dim(right_data);
end
%增加分割域
node=cat(2,node,dimension);
%将左右结点的结果加入树中
KDTree={node,left_node,right_node};

邻近点搜索函数 KD_Tree_Search:

%针对二维数据的搜索近邻点,所构造的树需要具有分割域
function Nearest=KD_Tree_Search(KDTree,point)
%取出结点
node=KDTree{1,1};
%判定从左右枝搜索,默认为从左枝
Leaf=KDTree{1,2};
%判断是分割域,1为x轴,2为y轴
if node(1,3)==1
    if node(1,1)<point(1,1) 
        Leaf=KDTree{1,3};
    end
else
    if node(1,2)<point(1,2)     
        Leaf=KDTree{1,3};
    end
end
%判断是否是是叶子,如果是继续向下搜索,如果否,则计算其距离
if strcmp(class(Leaf),'cell')
    Result=KD_Tree_Search(Leaf,point);
    %将返回结果与当前结点的距离进行比较
    dist=sqrt((node(1,1)-point(1,1))^2+(node(1,2)-point(1,2))^2);
    %比较两个距离大小,取小
    if Result{1,2}<dist
        Nearest=Result{1,2};
    else
        Nearest={node(1:2),dist};
    end
else
    %判定是否为空值
    if ~isempty(Leaf)
        %计算两点的距离
        dist1=sqrt((Leaf(1,1)-point(1,1))^2+(Leaf(1,2)-point(1,2))^2);
        %计算与结点的距离
        dist2=sqrt((node(1,1)-point(1,1))^2+(node(1,2)-point(1,2))^2);
        %比较两个距离大小,取小
        if dist1<dist2
            Nearest={Leaf,dist1};
        else
            Nearest={node(1:2),dist2};
        end
    end
end

测试数据如下,请读者赋值保存为txt:

2	3
5	4
9	6
4	7
8	1
7	2

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值