清华数据结构平均气温AC100

本文介绍了如何使用2D Range Tree解决数据结构中的平均气温查询问题,详细阐述了算法思想和步骤,包括创建AVL树、站点排序、节点插入以及查找过程。虽然FC Tree能更高效地解决,但2D Range Tree实现相对简单,适合初学者理解。文中还提到了KD-Tree在此问题上的不足,并提供了完整代码和100分的解题证明。
摘要由CSDN通过智能技术生成

写在最前:

这道题,其实最节约时间的算法应该是用FC tree,用该数据结构可以在logn的时间内算出来。

但是,说实话,我写不出这样的树出来,至少目前没必要,因为这样太麻烦了,关键是指针不好指。

所以,我用的是2d range tree。用该数据结构可以在logn^2的时间内算出来!

该数据结构的思想为:

1)先创建AVL树,树的每个节点为站点值

2)将站点按x进行从小到大排序,排序完毕之后,依次插入AVL树的叶子节点中。

并且,站点数组的每个数据留一个指针指向最后的叶子节点,方便后面查找用

同时,还将y数组排序好了给每一个节点!

这一段不看也没事

(这里比较神奇的是,最后插完,刚好只有一个叶子节点的一个右孩子是未被插入的,这个在数学上也是可以解释的,因为叶子的孩子节点数之和刚好比总结点数多1)

解释如下:n个节点,有2n个孩子指针。而2n个孩子指针,需要指向n-1个节点(其中有一个被根节点指了),因此剩余n+1个孩子指针。故再次插入n个节点后,剩余1个指针。而我们插入的顺序是由左至右,即由小到大,故最右边的叶子节点的右孩子指针为空。

 

3)对于每个X1,X2,Y1,Y2。这里我们对x进行2分查找,找到后即可通过预留的指针找到对应的最末端叶子节点

4)然后顺次走到根节点,只需做的是root=root->parent。

这里需要注意的是,每向上走一步,要留一个指针指向原来的位置,这样我们要是想从交点处回来,也方便!

5)找到x1,x2对应的共同节点,然后共同节点往下走,查找每个节点对应的左子树或者右子树即可!

6)对于每颗右子树或者左子树,他们的x值是不用管的,肯定满足,但是y值是要用二分查找找到的,因此需要花费logn的时间

查找到一个y值,就+它的气温,最后得到总气温了!

如果思路还是看不懂,可以详见https://blog.csdn.net/liuqiyao_01/article/details/8478719

或者看图

 最后,附上代码!

#pragma warning(disable:4996)
#include <stdio.h>
#include "temperature.h"
#define maxn 50000
using namespace std;
struct range_node;//范围查询的节点构成范围查询树
//station_type是每一个观测站的具体内容(包括了x,y坐标,温度temp,
//观测站内部还有一个指针c,是用来指向叶子节点,然后用来回溯路径)
//一个指针road,用来指向前一个节点
typedef struct _station_type
{
	int x, y;
	int temp;
	_station_type&operator=(const _station_type&data)
	{
		temp = data.temp;
		x = data.x;
		y = data.y;
		return *this;
	}
	range_node*c,*road=NULL;
} station_type;
station_type stations[maxn];
//fctree是用来构建y值数组,每个fctree中都含有station_type类型的data
//y值比较大小,当y值相同时,看x值,这里不可能出现x与y值相同
struct fctree {
	station_type data;
	bool operator>(const fctree&a)
	{
		if (data.y > a.data.y)return true;
		else if (data.y == a.data.y) {
			if (data.x > a.data.x)return true;
			else return false;
		}
		else return false;
	}
	bool operator<(const fctree&a)
	{
		if (data.y < a.data.y)return true;
		else if (data.y == a.data.y) {
			if (data.x < a.data.x)return true;
			else return false;
		}
		else return false;
	}
};
//每个节点都有左右指针和对应的y值
//首先要构建AVL树
struct range_node {
	range_node*rc, *lc, *parent;
	fctree*fc;//这个指针用于指向y数值的数组,记得初始化时要用new fc来确定它的数组大小
	int fc_size = 0;
	station_type data;//每个节点中都只有一个数据点
	int height = 0;
	range_node() { rc = lc = NULL; fc = NULL; parent = NULL; }
	range_node(const station_type&e, range_node*p, 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值