1. 程式人生 > >k-d tree程式碼解析

k-d tree程式碼解析

//KDTree::是由於定義了KDTree的namespace
KDTree::KDTreeNode* KDTree::KDTree::createKDTree( const ExamplarSet &exm_set )
{
if(exm_set.empty())
return NULL;

ExamplarSet exm_set_copy(exm_set);

int dims = exm_set_copy.getDims();
int size = exm_set_copy.getSize();

//計算每個維的方差,選出方差值最大的維 double
var_max = -0.1;
double avg, var;
int dim_max_var = -1;
for(int i=0;i<dims;i++)
{
avg = 0;
var = 0;
//求某一維的總和 for(int j=0;j<size;j++)
{
avg += exm_set_copy[j][i];
}
//求平均 avg /= size;
//求方差 for(int j=0;j<size;j++)
{
var
+= ( exm_set_copy[j][i] - avg ) *
( exm_set_copy[j][i] - avg );
}
var /= size;
if(var > var_max)
{
var_max = var;
dim_max_var = i;
}
}

//確定節點的資料向量 _HyperRectangle hr = exm_set_copy.calculateRange(); //統計節點空間範圍 exm_set_copy.sortByDim(dim_max_var); //
將所有資料向量按最大區分度方向排序 int mid = size / 2;
_Examplar exm_split = exm_set_copy.examplarAt(mid); //取出排序結果的中間節點 exm_set_copy.remove(mid); //將中間節點作為父(根)節點,所有將其從資料集中去除

//確定左右節點 ExamplarSet exm_set_left(0, exm_set_copy.getDims());
ExamplarSet exm_set_right(0, exm_set_copy.getDims());
exm_set_right.remove(0);

int size_new = exm_set_copy.getSize(); //獲得子資料空間大小 for(int i=0;i<size_new;i++) //生成左右子節點 {
_Examplar temp = exm_set_copy[i];
if( temp.dataAt(dim_max_var) <
exm_split.dataAt(dim_max_var) )
exm_set_left.push_back(temp);
else
exm_set_right.push_back(temp);
}

KDTreeNode *pNewNode = new KDTreeNode(0, 0, 0, dim_max_var, exm_split, hr);
pNewNode->_left_child = createKDTree(exm_set_left); //遞迴呼叫生成左子樹 if(pNewNode->_left_child != NULL) //確認左子樹父節點 pNewNode->_left_child->_parent = pNewNode;
pNewNode->_right_child = createKDTree(exm_set_right); //遞迴呼叫生成右子樹 if(pNewNode->_right_child != NULL) //確認右子樹父節點 pNewNode->_right_child->_parent = pNewNode;

return pNewNode; //最終返回k-d tree的根節點}