range tree范围树

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
#define BinNodePos BinNode* 
typedef struct Point{//二维坐标类
	int x;
	int y;
	Point() { x = 0; y = 0; }
	Point(int xx, int yy) :x(xx), y(yy) {};
};
bool cmp(Point &a, Point &b) {//比较函数,用于为坐标排序
	return (a.x != b.x) ? a.x < b.x : a.y < b.y;
}
class BinNode {//二叉树节点
public:
	int x;
	BinNodePos pr;
	BinNodePos lc;
	BinNodePos rc;
	vector<int> y;//range tree 的每一个节点都是x坐标相同的节点的集合,y节点储存在向量内
	BinNode(int _x) {
		x = _x;
		pr = NULL;
		lc = NULL;
		rc = NULL;
	}
};
class AVL {
public:
	BinNodePos root;
	int size;
	AVL() {
		root = NULL;
		size = 0;
	}
	BinNodePos cstX(vector<BinNodePos> x, BinNodePos prt, int lo, int hi) {//使用已排序的节点,二分递归创建二叉平衡树
		if (hi - lo == 1)	return x[lo];
		if (hi == lo)	return NULL;
		int mi = (lo + hi) / 2;
		BinNodePos bn = x[mi];
		bn->pr = prt;
		bn->lc = cstX(x, bn, lo, mi);
		bn->rc = cstX(x, bn, mi + 1, hi);
		return bn;
	}
	void print(Point *pt, int n) {//打印
		for (int i = 0; i < n; i++) {
			cout << "(" << pt[i].x << "," << pt[i].y << ")" << " ";
		}
		cout << endl;
	}
	void construct(Point *pt,int n) {//创建二叉平衡树
		sort(pt, pt + n, cmp);//现将所有的点排序
		print(pt, n);
		vector<BinNodePos> xNode;//x节点相同,y节点不同的二叉树节点集合
		int x = pt[0].x;
		BinNodePos b = new BinNode(x);//当前节点
		b->y.push_back(pt[0].y);
		for (int i = 1; i < n; i++) {
			if (x == pt[i].x) {//如果相同,直接将y值加进去
				b->y.push_back(pt[i].y);
			}
			else {//不是,则将当前节点加入集合,然后再创建一个
				x = pt[i].x;
				xNode.push_back(b);
				b = new BinNode(x);
				b->y.push_back(pt[i].y);
			}
		}
		if (xNode[xNode.size() - 1]->x != b->x)	xNode.push_back(b);//处理最后一个节点
		size = xNode.size();
		root = cstX(xNode, NULL, 0, xNode.size());//将处理好的二叉树节点递归建树
	}
	void visit(BinNodePos x) {
		for (int i = 0; i < x->y.size(); i++) {
			cout << "(" << x->x << "," << x->y[i] << ")"<<" ";
		}
	}
	void search(BinNodePos x, Point a, Point b) {//中序递归范围搜索
		if (x == NULL) return;
		if (x->x > a.x)	search(x->lc, a, b);
		if (x->x <= b.x && x->x >= a.x) {
			for (int i = 0; i < x->y.size(); i++) {
				if(x->y[i]<=b.y&&x->y[i]>=a.y)	cout<< "(" << x->x << "," << x->y[i] << ")" << " ";
			}
			cout << endl;
		}
		if (x->x < b.x)	search(x->rc, a, b);
	}
	void traverse_mid(BinNodePos x) {//中序递归
		if (x == NULL)	return;
		traverse_mid(x->lc);
		visit(x);
		traverse_mid(x->rc);
	}
};
int main() {
	Point *pt;
	int n;
	while (cin >> n) {
		pt = new Point[n];
		for (int i = 0; i < n; i++) {
			cin >> pt[i].x >> pt[i].y;
		}
		cout << endl;
		AVL avl;
		avl.construct(pt, n);
		avl.traverse_mid(avl.root);
		avl.search(avl.root, Point(0, 2), Point(3, 4));
	}
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
K-D Tree(K-Dimensional Tree)是一种用于处理 k 维空间数据的数据结构。它可以用于搜索最近邻点、范围搜索等问题。下面是一个简单的 Python 实现。 首先,我们需要一个节点类来表示中的节点: ```python class Node: def __init__(self, point=None, axis=None, left=None, right=None): self.point = point # 节点代表的点 self.axis = axis # 划分轴 self.left = left # 左子 self.right = right # 右子 ``` 接下来,我们需要一个 `build_kdtree` 函数来构建 K-D Tree: ```python def build_kdtree(points, depth=0): n = len(points) if n <= 0: return None axis = depth % k # 选择轴 points.sort(key=lambda point: point[axis]) mid = n // 2 return Node( point=points[mid], axis=axis, left=build_kdtree(points[:mid], depth+1), right=build_kdtree(points[mid+1:], depth+1) ) ``` 这个函数会递归地将点集分成两部分,构建 K-D Tree。 接下来,我们需要实现两个重要的子函数:`nearest_neighbor` 和 `range_search`。 `nearest_neighbor` 函数用于查找 K-D Tree 中最近的点: ```python def nearest_neighbor(root, point): best = None best_distance = float("inf") def search(node, depth=0): nonlocal best, best_distance if node is None: return distance = euclidean_distance(point, node.point) if distance < best_distance: best = node.point best_distance = distance axis = depth % k if point[axis] < node.point[axis]: search(node.left, depth+1) if point[axis] + best_distance >= node.point[axis]: search(node.right, depth+1) else: search(node.right, depth+1) if point[axis] - best_distance <= node.point[axis]: search(node.left, depth+1) search(root) return best ``` 这个函数会从根节点开始递归地搜索 K-D Tree,找到与目标点最近的点。 最后,我们需要实现 `range_search` 函数来查找 K-D Tree 中给定范围内的所有点: ```python def range_search(root, lower, upper): result = [] def search(node, depth=0): if node is None: return if lower <= node.point <= upper: result.append(node.point) axis = depth % k if lower[axis] <= node.point[axis]: search(node.left, depth+1) if upper[axis] >= node.point[axis]: search(node.right, depth+1) search(root) return result ``` 这个函数会从根节点开始递归地搜索 K-D Tree,找到所有满足条件的点。 完整的代码如下所示: ```python import math k = 2 class Node: def __init__(self, point=None, axis=None, left=None, right=None): self.point = point # 节点代表的点 self.axis = axis # 划分轴 self.left = left # 左子 self.right = right # 右子 def euclidean_distance(p, q): return math.sqrt(sum((p[i] - q[i])**2 for i in range(k))) def build_kdtree(points, depth=0): n = len(points) if n <= 0: return None axis = depth % k # 选择轴 points.sort(key=lambda point: point[axis]) mid = n // 2 return Node( point=points[mid], axis=axis, left=build_kdtree(points[:mid], depth+1), right=build_kdtree(points[mid+1:], depth+1) ) def nearest_neighbor(root, point): best = None best_distance = float("inf") def search(node, depth=0): nonlocal best, best_distance if node is None: return distance = euclidean_distance(point, node.point) if distance < best_distance: best = node.point best_distance = distance axis = depth % k if point[axis] < node.point[axis]: search(node.left, depth+1) if point[axis] + best_distance >= node.point[axis]: search(node.right, depth+1) else: search(node.right, depth+1) if point[axis] - best_distance <= node.point[axis]: search(node.left, depth+1) search(root) return best def range_search(root, lower, upper): result = [] def search(node, depth=0): if node is None: return if lower <= node.point <= upper: result.append(node.point) axis = depth % k if lower[axis] <= node.point[axis]: search(node.left, depth+1) if upper[axis] >= node.point[axis]: search(node.right, depth+1) search(root) return result ``` 这是一个简单的 K-D Tree 的 Python 实现,可以用来解决搜索最近邻点、范围搜索等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值