四叉树的C++实现

四叉树的数据结构
抽象数据类型定义如下:

ADT QuadTrees{
	数据对象D:D是具有相同性质的具有二维结构的数据元素的集合,本实验为坐标数据。
	数据关系R:若D为空集,则称为空树;若D仅含有一个数据元素,则R为空集,否则R={H},	H是如下二元关系:
	(1) 在D中存在唯一的元素root,它在关系H下无父节点;
	(2) D中任意元素d将其子节点划分为四个象限,将其直接相邻的节点分别设为d[1],d[2],d[3],d[4](3) 若D-{root}≠ɸ,则存在D-{root} ={root[1],root[2],root[3],root[4]},且两两无交集;
	(4) 若d[i] ≠ɸ(i=1,2,3,4),则d[i]中存在唯一的xi ,<root, xi> ∈H,且存在d[i]上的关系Hi⊂H;
	       H={<root, xi>, Hi},i=1,2,3,4;
	(5) (root[i],{Hi})i=1,2,3,4 是符合定义的四叉树;
	基本操作:
	QuadTreeInit(QT);//构造空的四叉树
	Compare(node A, node B);//返回B在A的第几个象限,返回值取之只能为1,2,3,4
	StaightforwardInsertion(QT,K);//简单插入节点K(不考虑树的平衡)
	SophisticatedInsertion(QT,K);//插入节点K(考虑树的平衡)
	RegionSearch(QT,K,double L,R,B,T);//查找节点K所有在x=L,x=B,y=R,y=T所构成矩形区域的子节点
	}ADT QuadTrees;

算法实现
四叉树给出如下定义:
一棵四叉树T是由一个或一个以上节点组成的有限集,其中有一个特定的节点R称为T的根节点。如果集合( T - { R } ) 非空,那么集合中的这些点被划分为n(n≤4)个不相交的子集 ,其中每个子集都是四叉树,并且其相应的根节点 是R的子节点。子集 称为T 的子树。
四叉树与对应节点关系:

四叉树与对应节点关系对照

以下是源码:

#include <vector>
#include <iostream>
using namespace std;

template<typename T>
struct Point{
	T x;
	T y;
	Point(){}
	Point(T _x, T _y) :x(_x), y(_y){}
};

template<typename T>
struct Node{
	Node* R[4];
	Point<T> pt;
	Node* parent;
};

template<typename ElemType>
class QuardTree
{
public:
	QuardTree();
	~QuardTree();
	void Insert(const Point<ElemType>& pos);
	void BalanceInsert(const Point<ElemType>& pos );
	int nodeCount();
	int TPLS();
	int Height();
	void RegionResearch(ElemType left, ElemType right, ElemType botom, ElemType top, int& visitednum,int& foundnum);
	void clear();
private:
	Node<ElemType>* root;
	int Compare(const Node<ElemType>* node, const Point<ElemType>& pos);
	bool In_Region(Point<ElemType> t, ElemType left, ElemType right, ElemType botom, ElemType top);
	bool Rectangle_Overlapse_Region(ElemType L, ElemType R, ElemType B, ElemType T, ElemType left, ElemType right, ElemType botom, ElemType top);
	void RegionResearch(Node<ElemType>* t, ElemType left, ElemType right, ElemType botom, ElemType top, int& visitednum, int& foundnum);
	int Depth(Node<ElemType>* &);
	int nodeCount(const Node<ElemType>*);
	void clear(Node < ElemType>*& p);
	void Insert(Node<ElemType>*& , const Point<ElemType>& pos);//递归插入节点
};


template<typename T>
QuardTree<T>::QuardTree()
{
	root = NULL;
}

template<typename T>
QuardTree<T>::~QuardTree()
{
	clear(root);
}

template<typename T>
int QuardTree<T>::TPLS()
{
	return Depth(root);
}

template<typename T>
int QuardTree<T>::Compare(const Node<T>* node, const Point<T>& pos)
{
	if (pos.x == node->pt.x && pos.y == node->pt.y) return 0;
	if (pos.x >= node->pt.x && pos.y>node->pt.y)  return 1;
	if (pos.x<node->pt.x  && pos.y >= node->pt.y) return 2;
	if (pos.x <= node->pt.x && pos.y<node->pt.y)  return 3;
	if (pos.x>node->pt.x  && pos.y <= node->pt.y) return 4;
	return -1;
}


template<typename T>
void QuardTree<T>::BalanceInsert(const Point<T>& pos)
{
	Node<T>* node = (Node<T>*)malloc(sizeof(Node<T>));
	node->R[0] = NULL;
	node->R[1] = NULL;
	node->R[2] = NULL;
	node->R[3] = NULL;
	node->parent = NULL;
	node->pt = pos;
	if (root == NULL)
	{
		root = node;
		return;
	}
	Node<T>* temp = root;
	int direction = Compare(temp, pos);
	if (direction == 0) return;
	while (temp->R[direction - 1] != NULL)
	{
		temp = temp->R[direction - 1];
		direction = Compare(temp, pos);
		if (direction == 0) return;
	}
	temp->R[direction - 1] = node;
	node->parent = temp;
	
	Node<T>* tp = temp->parent;
	if (tp == NULL) return;
	int r = Compare(tp, temp->pt);

	if (abs(direction-r) == 2)
	{
		Node<T>* leaf = node;
		if (tp->R[abs(3 - r)] == NULL )
		{
			tp->R[r - 1] = NULL;
			temp->parent = leaf;
			leaf->R[r-1] = temp;

			temp->R[abs(3 - r)] = NULL;
			Node<T>* Rt = tp->parent;
			if (Rt == NULL)
			{
				root = leaf;
				leaf->parent = NULL;

				leaf->R[abs(3 - r)] = tp;
				tp->parent = leaf;
				return;
			}
			tp->parent = NULL;
			int dd = Compare(Rt, tp->pt);

			Rt->R[dd - 1] = leaf;
			leaf->parent = Rt;

			leaf->R[abs(3 - r)] = tp;
			tp->parent = leaf;
		}
	}	
}


template<typename T>
void QuardTree<T>::Insert(Node<T>*& p, const Point<T>& pos)
{
	if (p == NULL)
	{
		Node<T>* node = (Node<T>*)malloc(sizeof(Node<T>));
		node->R[0] = NULL;
		node->R[1] = NULL;
		node->R[2] = NULL;
		node->R[3] = NULL;
		node->pt = pos;
		p = node;
		return;
	}
	else
	{
		int d = Compare(p, pos);
		if (d == 0) return;
		Insert(p->R[d - 1], pos);
	}
}


template<typename T>
void QuardTree<T>::Insert(const Point<T>& pos)
{
	int direction, len = 0;
	Node<T>* node = (Node<T>*)malloc(sizeof(Node<T>));
	node->R[0] = NULL;
	node->R[1] = NULL;
	node->R[2] = NULL;
	node->R[3] = NULL;
	node->pt = pos;
	if (root == NULL)
	{
		root = node;
		return;
	}
	direction = Compare(root, pos);
	Node<T>* temp = root;
	if (direction == 0) return;//节点已存在 
	len = 1;
	while (temp->R[direction - 1] != NULL)
	{
		temp = temp->R[direction - 1];
		direction = Compare(temp, pos);
		if (direction == 0) return;
	}
	temp->R[direction - 1] = node;
	//Insert(root, pos);//递归插入节点
}





template<typename T>
int QuardTree<T>::nodeCount()
{
	return nodeCount(root);
}

template<typename T>
int QuardTree<T>::nodeCount(const Node<T>* node)
{
	if (node == NULL) return 0;
	return 1 + nodeCount(node->R[0]) + nodeCount(node->R[1]) + nodeCount(node->R[2]) + nodeCount(node->R[3]);
}

template<typename T>
bool QuardTree<T>::In_Region(Point<T> t, T left, T right, T botom, T top)
{
	return t.x >= left && t.x <= right && t.y >= botom && t.y <= top;
}

template<typename ElemType>
bool QuardTree<ElemType>::Rectangle_Overlapse_Region(ElemType L, ElemType R, ElemType B, ElemType T, 
	ElemType left, ElemType right, ElemType botom, ElemType top)
{
	return L <= right && R >= left && B <= top && T >= botom;
	//return true;
}//优化查找速度

template<typename T>
void QuardTree<T>::RegionResearch(Node<T>* t, T left, T right, T botom, T top, int& visitednum, int& foundnum)
{
	if (t == NULL) return;
	T xc = t->pt.x;
	T yc = t->pt.y;
	if (In_Region(t->pt, left, right, botom, top)){ ++foundnum; }
	if (t->R[0] != NULL && Rectangle_Overlapse_Region(xc, right, yc, top, left, right, botom, top))
	{
		visitednum++;
		RegionResearch(t->R[0], xc>left?xc:left, right, yc>botom?yc:botom, top, visitednum, foundnum);
	}
	if (t->R[1] != NULL && Rectangle_Overlapse_Region(left, xc, yc, top, left, right, botom, top))
	{
		visitednum++;
		RegionResearch(t->R[1], left, xc>right?right:xc, yc>botom?yc:botom, top, visitednum, foundnum);
	}
	if (t->R[2] != NULL && Rectangle_Overlapse_Region(left, xc, botom, yc, left, right, botom, top))
	{
		visitednum++;
		RegionResearch(t->R[2], left, xc<right?xc:right, botom, yc<top?yc:top, visitednum, foundnum);
	}
	if (t->R[3] != NULL && Rectangle_Overlapse_Region(xc, right, botom, yc, left, right, botom, top))
	{
		visitednum++;
		RegionResearch(t->R[3], xc>left ? xc : left, right, botom, yc<top ? yc : top, visitednum, foundnum);
	}
}

template<typename T>
void QuardTree<T>::clear()
{
	clear(root);
}

template<typename T>
void QuardTree<T>::clear(Node<T>* &p)
{
	if (p == NULL) return;
	if (p->R[0]) clear(p->R[0]);
	if (p->R[1]) clear(p->R[1]);
	if (p->R[2]) clear(p->R[2]);
	if (p->R[3]) clear(p->R[3]);
	free(p);
	p = NULL;
}

template<typename T>
void QuardTree<T>::RegionResearch(T left, T right, T botom, T top, int& visitednum, int& foundnum)
{
	RegionResearch(root, left, right, botom, top, visitednum,foundnum);
}

template<typename T>
int QuardTree<T>::Depth(Node<T>* &node)
{
	if (node == NULL) return 0;
	int dep = 0;
	Node<T>* tp = root;
	while (tp->pt.x!=node->pt.x || tp->pt.y!=node->pt.y)
	{
		dep++;
		tp = tp->R[Compare(tp, node->pt) - 1];
		if (tp == NULL) break;
	}
	return dep + Depth(node->R[0]) + Depth(node->R[1]) + Depth(node->R[2]) + Depth(node->R[3]);
}

参考文献
Finkel R A, Bentley J L. Quad trees a data structure for retrieval on composite keys[J]. Acta Informatica, 1974, 4(1):1-9.

  • 7
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 以下是C#语言实现四叉树的代码: ```csharp using System.Collections.Generic; using UnityEngine; public class QuadTree { private int capacity = 4; private int depth = 0; private int maxDepth = 5; private List<GameObject> objects; private Bounds bounds; private QuadTree[] nodes; public QuadTree(int depth, Bounds bounds) { this.depth = depth; this.bounds = bounds; objects = new List<GameObject>(); nodes = new QuadTree[4]; } public void Insert(GameObject obj) { if (!bounds.Contains(obj.transform.position)) return; if (objects.Count < capacity || depth == maxDepth) { objects.Add(obj); } else { if (nodes[0] == null) Split(); nodes[0].Insert(obj); nodes[1].Insert(obj); nodes[2].Insert(obj); nodes[3].Insert(obj); } } public List<GameObject> Retrieve(GameObject obj) { List<GameObject> objs = new List<GameObject>(); if (bounds.Contains(obj.transform.position)) { foreach (GameObject o in objects) objs.Add(o); if (nodes[0] != null) { objs.AddRange(nodes[0].Retrieve(obj)); objs.AddRange(nodes[1].Retrieve(obj)); objs.AddRange(nodes[2].Retrieve(obj)); objs.AddRange(nodes[3].Retrieve(obj)); } } return objs; } private void Split() { float subWidth = bounds.size.x / 2f; float subHeight = bounds.size.y / 2f; float x = bounds.center.x; float y = bounds.center.y; nodes[0] = new QuadTree(depth + 1, new Bounds(new Vector3(x + subWidth / 2f, y + subHeight / 2f, 0f), new Vector3(subWidth, subHeight, 1f))); nodes[1] = new QuadTree(depth + 1, new Bounds(new Vector3(x - subWidth / 2f, y + subHeight / 2f, 0f), new Vector3(subWidth, subHeight, 1f))); nodes[2] = new QuadTree(depth + 1, new Bounds(new Vector3(x - subWidth / 2f, y - subHeight / 2f, 0f), new Vector3(subWidth, subHeight, 1f))); nodes[3] = new QuadTree(depth + 1, new Bounds(new Vector3(x + subWidth / 2f, y - subHeight / 2f, 0f), new Vector3(subWidth, subHeight, 1f))); } } ``` 这是一个简单的四叉树实现,用于对游戏中的物体进行空间划分。四叉树是一种递归地将空间划分成四个象限的数据结构,每个节点可以容纳一定数量的物体。当节点的物体数量超过容量时,节点会被细分成四个子节点。这样可以提高物体的查找效率,避免遍历整个场景中的所有物体。 ### 回答2: 四叉树是一种用于将二维空间划分为多个小区域的数据结构,常用于解决涉及空间索引和查询的问题。以下是用C#语言实现四叉树的代码示例: ```csharp using System.Collections.Generic; public class QuadTree { private Node root; public QuadTree(double x, double y, double width, double height) { root = new Node(x, y, width, height); } public void Insert(Point point) { root.Insert(point); } public List<Point> QueryRange(double x, double y, double width, double height) { List<Point> pointsInRange = new List<Point>(); root.QueryRange(x, y, width, height, ref pointsInRange); return pointsInRange; } private class Node { private double x; private double y; private double width; private double height; private List<Point> points; private Node topLeft; private Node topRight; private Node bottomLeft; private Node bottomRight; public Node(double x, double y, double width, double height) { this.x = x; this.y = y; this.width = width; this.height = height; points = new List<Point>(); topLeft = null; topRight = null; bottomLeft = null; bottomRight = null; } public void Insert(Point point) { if (!Contains(point)) return; if (points.Count < 4) { points.Add(point); } else { if (topLeft == null) Split(); topLeft.Insert(point); topRight.Insert(point); bottomLeft.Insert(point); bottomRight.Insert(point); } } public void QueryRange(double x, double y, double width, double height, ref List<Point> pointsInRange) { if (!Intersects(x, y, width, height)) return; foreach (Point point in points) { if (point.X >= x && point.X <= x + width && point.Y >= y && point.Y <= y + height) pointsInRange.Add(point); } if (topLeft != null) { topLeft.QueryRange(x, y, width, height, ref pointsInRange); topRight.QueryRange(x, y, width, height, ref pointsInRange); bottomLeft.QueryRange(x, y, width, height, ref pointsInRange); bottomRight.QueryRange(x, y, width, height, ref pointsInRange); } } private bool Contains(Point point) { return point.X >= x && point.X <= x + width && point.Y >= y && point.Y <= y + height; } private bool Intersects(double rangeX, double rangeY, double rangeWidth, double rangeHeight) { return x < rangeX + rangeWidth && x + width > rangeX && y < rangeY + rangeHeight && y + height > rangeY; } private void Split() { double halfWidth = width / 2; double halfHeight = height / 2; topLeft = new Node(x, y, halfWidth, halfHeight); topRight = new Node(x + halfWidth, y, halfWidth, halfHeight); bottomLeft = new Node(x, y + halfHeight, halfWidth, halfHeight); bottomRight = new Node(x + halfWidth, y + halfHeight, halfWidth, halfHeight); foreach (Point point in points) { topLeft.Insert(point); topRight.Insert(point); bottomLeft.Insert(point); bottomRight.Insert(point); } points.Clear(); } } } public class Point { public double X { get; } public double Y { get; } public Point(double x, double y) { X = x; Y = y; } } ``` 以上是用C#语言编写的简单四叉树实现代码。在QuadTree类中,构造函数初始化根节点,Insert方法用于将点插入四叉树中,QueryRange方法用于查询给定范围内的所有点。内部的Node类表示四叉树的节点,包括节点的坐标范围、存储的点、以及四个子节点。四叉树的划分采用递归的方式,当节点内的点数量达到阈值时会自动进行划分。希望这能帮助到你! ### 回答3: 下面是用C#语言实现四叉树的代码示例: ```csharp using System; using System.Collections.Generic; public class QuadTreeNode { public int x; public int y; public QuadTreeNode[] children; public bool isLeaf; public QuadTreeNode(int x, int y) { this.x = x; this.y = y; children = new QuadTreeNode[4]; isLeaf = true; } } public class QuadTree { public QuadTreeNode root; public QuadTree(int x, int y) { root = new QuadTreeNode(x, y); } public void Insert(int x, int y) { Insert(root, x, y); } private void Insert(QuadTreeNode node, int x, int y) { if (node.isLeaf) { // 如果节点是叶子节点,将节点扩展为四个子节点 Split(node); } // 将数据插入到子节点中 int quadrant = GetQuadrant(node, x, y); Insert(node.children[quadrant], x, y); } private void Split(QuadTreeNode node) { int childX = node.x; int childY = node.y; int childWidth = node.isLeaf ? 1 : node.children[0].x - node.x; for (int i = 0; i < 4; i++) { node.children[i] = new QuadTreeNode(childX, childY); childX += childWidth; } node.isLeaf = false; } private int GetQuadrant(QuadTreeNode node, int x, int y) { if (x < node.x + (node.children[0].x - node.x) / 2) { if (y < node.y + (node.children[0].y - node.y) / 2) { return 0; // 左上 } else { return 2; // 左下 } } else { if (y < node.y + (node.children[0].y - node.y) / 2) { return 1; // 右上 } else { return 3; // 右下 } } } public void Print() { Print(root, ""); } private void Print(QuadTreeNode node, string indent) { Console.WriteLine(indent + "(" + node.x + ", " + node.y + ")"); if (!node.isLeaf) { for (int i = 0; i < 4; i++) { Print(node.children[i], indent + " "); } } } } public class Program { public static void Main(string[] args) { QuadTree quadTree = new QuadTree(0, 0); quadTree.Insert(1, 1); quadTree.Insert(2, 3); quadTree.Insert(4, 5); quadTree.Insert(6, 7); quadTree.Print(); } } ``` 上述代码实现了一个简单的四叉树数据结构。QuadTreeNode表示四叉树的节点,包含节点的坐标和四个子节点;QuadTree表示四叉树,包含根节点和插入数据的方法。在Insert方法中,会根据数据的坐标计算出应该插入的子节点,并递归地进行插入操作。Split方法用于将叶子节点扩展为四个子节点。GetQuadrant方法用于根据坐标获取节点所在的象限。Print方法用于打印四叉树的结构。 在Main方法中,我们创建了一个QuadTree对象,然后插入了一些数据,并打印整个四叉树的结构。您可以修改Main方法中的插入操作和添加更多数据,以测试四叉树的功能。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值