k近邻法中kd-tree树的创建

来源:互联网 发布:exsi虚拟机linux网络 编辑:程序博客网 时间:2024/06/06 00:58

经过一天努力实现了kd-tree树二维的创建,但是代码只适用于二维,这是令人遗憾的地方。

在这个过程中学到了不少东西,特别是对vector的一些用法,多了更多的了解。

思路:创建树时,传递vector为形参,以第n%2维为变量,对结构体vector排序,找出中位数,奇数找中间,

偶数取第(n/2)+1个,以它为分界线,左边的放在vector<>a中,右边的数放在vector<>b中,中位数那个点,

保存为节点,递归调用创建左右子树。

代码限制普适性的地方:1、创建了点的结构体

                                            2、找到操作维数,并对其操作的代码

学到的用法:

1、vector可当形参,而且跟其他形参一样,函数中的操作可不影响原vector

#include<iostream>#include<vector>using namespace std;void f(vector<int> x){x[0]=0;}int main(){vector<int> a;a.push_back(1);a.push_back(2);f(a);cout<<a[0];return 0;}


结果:


2、istringstream的运用,对于数据的输入很方便

void kdTree::dataIn(){ifstream in("data.txt");string str;for(int i=0;i<N;i++){getline(in,str);istringstream t(str);t>>dataValue[i].x;t>>dataValue[i].y;}}


3、c++访问控制

第一:private, public, protected 访问标号的访问范围。
private:只能由1.该类中的函数、2.其友元函数访问。
不能被任何其他访问,该类的对象也不能访问。
protected:可以被1.该类中的函数、2.子类的函数、以及3.其友元函数访问。
但不能被该类的对象访问。
public:可以被1.该类中的函数、2.子类的函数、3.其友元函数访问,也可以由4.该类的对象访问。
 注:友元函数包括3种:设为友元的普通的非成员函数;设为友元的其他类的成员函数;设为友元类中的所有成员函数。
第二:类的继承后方法属性变化。
private 属性不能够被继承。
使用private继承,父类的protected和public属性在子类中变为private;
使用protected继承,父类的protected和public属性在子类中变为protected;
使用public继承,父类中的protected和public属性不发生改变;

4、vector的排序

bool SortByX( const Point &v1, const Point &v2)//注意:本函数的参数的类型一定要与vector中元素的类型一致  {      return v1.x < v2.x;//x按升序排列  }
sort(v.begin(),v.end(),SortByX);


kd-tree创建
#include<iostream>#include<fstream>#include <sstream>#include<string>#include<vector>using namespace std;const int N=6;//the number of sample//const int K=2;//the div of sample//vector<int> T;// 1thclass Point{public: int x; int y;} ;vector<Point> R;class kdTreeNode{public:Point value;kdTreeNode*left;kdTreeNode*right;};class kdTree{        public:    kdTreeNode*head;    Point dataValue[N];void dataIn();//从文件中输入数据 void dataOut();//查看dataValue[N]中数据 void dataOperate();//预处理 kdTreeNode*createTree(vector<Point> v,int n);//创建树 void lookKdTree(kdTreeNode*p);//先根遍历 };void kdTree::dataIn(){ifstream in("data.txt");string str;for(int i=0;i<N;i++){getline(in,str);istringstream t(str);t>>dataValue[i].x;t>>dataValue[i].y;}}void kdTree::dataOut(){for(int i=0;i<N;i++){cout<<dataValue[i].x<<'\t';cout<<dataValue[i].y<<endl; }}void kdTree::dataOperate(){for(int i=0;i<N;i++)R.push_back(dataValue[i]);}bool SortByX( const Point &v1, const Point &v2)//注意:本函数的参数的类型一定要与vector中元素的类型一致  {      return v1.x < v2.x;//x按升序排列  }bool SortByY( const Point &v1, const Point &v2)//注意:本函数的参数的类型一定要与vector中元素的类型一致  {      return v1.y < v2.y;//y按升序排列  }  kdTreeNode* kdTree::createTree(vector<Point> v,int n){if(v.empty())return NULL;kdTreeNode*p=new kdTreeNode;if(n%2==0){sort(v.begin(),v.end(),SortByX);p->value=v[v.size()/2];vector<Point> a;vector<Point> b;for(int i=0;i<v.size()/2;i++) a.push_back(v[i]);  for(int i=v.size()/2+1;i<v.size();i++) b.push_back(v[i]); p->left=createTree(a,n+1); p->right=createTree(b,n+1);} else{sort(v.begin(),v.end(),SortByY);p->value=v[v.size()/2];vector<Point> a;vector<Point> b;for(int i=0;i<v.size()/2;i++) a.push_back(v[i]);  for(int i=v.size()/2+1;i<v.size();i++) b.push_back(v[i]); p->left=createTree(a,n+1); p->right=createTree(b,n+1);}return p;}void kdTree::lookKdTree(kdTreeNode*p){if(p==NULL)return;cout<<p->value.x<<'\t'<<p->value.y<<endl;lookKdTree(p->left);lookKdTree(p->right);}int main(){kdTree tree;tree.dataIn();//tree.dataOut();tree.dataOperate();tree.head=tree.createTree(R,0);tree.lookKdTree(tree.head);return 0;}

输入:

data.txt


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

输出:

7 2

5 4

2 3

4 7

9 6

8 1



1 0
原创粉丝点击