Skyline query是多维度数据库中一种非常重要的point query,它最初由 Börzsönyi 等人于2001年提出。一个数据库中的数据对象(也就是空间中的点)可能有成千上万个,但是我们往往对其中一些更感兴趣,Skyline就是定义这里的“更感兴趣”的一种方式。如下图所示是美国纽约曼哈顿区的天际线(Skyline),显然这里的建筑有很多很多,但放眼望去我们所能看见的(也就是构成天际线,skyline算法也称为天际线算法)建筑其实是相当有限的。这些建筑要么是离我们特别近,要么是特别高大;换言之,也只有那些无法被完全遮挡的建筑才能被看到。Skyline query正是从这个想法出发提出的一种point query。

1.dominate定义

  对应于前面讨论的”被遮挡”这个概念,我们首先给出dominate的定义:

Definition of point dominate: a point A dominates another point B if and only if the coordinate of A on any axis
is not larger than the corresponding coordinate of B.dominate的定义:点 A dominate 点 B,当且仅当,A在任何轴的坐标值都小于等于B对应的轴的坐标值,并且不能全部等于.

  我们以海边酒店为例,我们打算在海边订到酒店,希望酒店离海边越近越好,并且希望价钱也越便宜越好,则在酒店这个对象上dominate的定义就是:

Definition: Hotel i dominates hotel fif both distance and price of hotel i are smaller than or equal to those of hotel f
AND both distance and price of hotel i are NOT equal to those of hotel f.定义: Hotel i dominate hotel f如果hotel i 到海边的距离和价钱都小于或等于hotel f到海边的距离和价钱,并且距离和价钱不全等
(部分等,不能全部等),那么就称hotel i dominate hotel f

以下图为例:其中点a dominate b和e; 点k dominate e和l; 点i dominate 除k和i外所有的点.

下面是dominate的另一些例子:

2.skyline point 定义

有了dominate的定义之后,我们再定义skyline point:

简而言之就是:skyline point 是点集中不会被其他点dominate的点

  所以我们的目标就是:找出所有的不能被其他点dominite的点。

以下面的酒店的例子为例:

图中酒店有两个属性,一个是离海边的距离distance,另一个是价格price。我们将其绘画到坐标轴上:

现在我们要找出没有被其他点dominate的点,具体实现是:
  首先维护一个酒店的最小堆,堆中元素大小定义为(distance + price)之和,为了便于表达,我们将distance替换为x,price替换为y,则是(x + y)之和。为了找到skyline point,我们需要利用以下性质:
1.堆中的第一个点(即最小点)一定是skyline point证明如下:假设该最小点m不是skyline point,也就是点m会被其他点dominate,假设这个点是点v。由于点v dominate 点m,也就意味着v的(x, y)一定小于或等于点m的(x, y),即xv<=xmandyv<=ym,并且二者不全等xv<=xmandyv<=ym,并且二者不全等x_v 。也就意味着(xv+yv); <=(xm,ym)(xv+yv);<=(xm,ym)(x_v + y_v);\ ,但是因为点m是堆中最小的点,也就是点m对应的(x+y)(x+y)(x+y)是最小的,所以这与点m是最小点冲突,则不存在这样的点v,所以堆中的第一个点(最小点)一定是skyline point

2.判断某个点v会不会被其他点dominate,我们只需要判断已经是skyline point的点能不能dominate点v,如果这些点无法dominate 点v,那么其他点更不用考虑。证明:首先,能够dominate 点v的点一定是先于v出最小堆的,因为它们拥有更小的x和y,也就会拥有更小的(x + y)。我们将先于点v出最小堆的点分为两大类,一类属于skyline point,假设为点集S;另一类不属于 skyline point,假设为点集U。点集U中的点,之所以不是skyline point,必定是被点集S中的点dominate,可能是直接dominate,也有可能是间接dominate,因为dominate具有传递性,即点a dominate 点b, 点b dominate 点c,那么点a 也必定dominate 点c,根据dominate的定义能很好理解。所以,如果点v能够被点集U中的点dominate,根据dominate的传递性,它也一定被点集S中的某个点dominate,所以如果点v不能被点集S中的点dominate, 则更不可能被点集U中的点dominate。综合起来,我们不用考虑点集U中的点,只需要考虑点集S中的点,得证。

3.代码实现

以上面的酒店例子为例,可以看出,skyline point有三个,点i,点a,和点k。

#include<bits/stdc++.h>
using namespace std;/*
*   定义一个hotel
*/
struct Hotel{string name;int dis;int price;Hotel(string s, int d, int p){name = s;dis = d;price = p;}
};struct cmp{bool operator () (const Hotel &a, const Hotel &b){return a.dis + a.price > b.dis + b.price;}
};bool isSkyLinePoint(vector<Hotel> S, Hotel h){for(int i = 0; i < S.size(); i++){if(S[i].dis <= h.dis){if(S[i].price <= h.price){if(S[i].price == h.price && S[i].dis == h.dis) return 1;return 0;}}}return 1;
}int main(){priority_queue<Hotel, vector<Hotel>, cmp> hotels;                                             //存放所有hotel的优先队列hotels.push(Hotel("a", 1, 9));hotels.push(Hotel("b", 2, 10));hotels.push(Hotel("c", 4, 8));hotels.push(Hotel("d", 6, 7));hotels.push(Hotel("e", 9, 10));hotels.push(Hotel("f", 7, 5));hotels.push(Hotel("g", 5, 6));hotels.push(Hotel("h", 4, 3));hotels.push(Hotel("i", 3, 2));hotels.push(Hotel("k", 9, 1));hotels.push(Hotel("l", 10, 4));hotels.push(Hotel("m", 6, 2));hotels.push(Hotel("n", 8, 3));//依次从最小堆中取出数据,并判断S集中的point能不能dominate这个需要判断的点vector<Hotel> S;while(!hotels.empty()){Hotel tmp = hotels.top();hotels.pop();if(isSkyLinePoint(S, tmp))S.push_back(tmp);}for(int i = 0; i < S.size(); i++)cout<<S[i].name<<endl;return 0;
}

skyline point解析相关推荐

  1. skyline二次开发:mpt简析

    做te开发的时候,最基本的还是要加一个mpt,没有mpt或者在线发布的mpt,连一个工程都不能打开,更不用说做别的. 作为商业软件,有些格式一定是限制的,而且也不是很显眼的被看出来,不能像cesium ...

  2. Cesium源码解析一(terrain文件的加载、解析与渲染全过程梳理)

    快速导航(持续更新中-) Cesium源码解析一(terrain文件的加载.解析与渲染全过程梳理) Cesium源码解析二(metadataAvailability的含义) Cesium源码解析三(m ...

  3. golang通过RSA算法生成token,go从配置文件中注入密钥文件,go从文件中读取密钥文件,go RSA算法下token生成与解析;go java token共用

    RSA算法 token生成与解析 本文演示两种方式,一种是把密钥文件放在配置文件中,一种是把密钥文件本身放入项目或者容器中. 下面两种的区别在于私钥公钥的初始化, init方法,需要哪种取哪种. 通过 ...

  4. List元素互换,List元素转换下标,Java Collections.swap()方法实例解析

    Java Collections.swap()方法解析 jdk源码: public static void swap(List<?> list, int i, int j) {// ins ...

  5. 条形码?二维码?生成、解析都在这里!

    二维码生成与解析 一.生成二维码 二.解析二维码 三.生成一维码 四.全部的代码 五.pom依赖 直接上代码: 一.生成二维码 public class demo {private static fi ...

  6. Go 学习笔记(82)— Go 第三方库之 viper(解析配置文件、热更新配置文件)

    1. viper 特点 viper 是一个完整的 Go应用程序的配置解决方案,它被设计为在应用程序中工作,并能处理所有类型的配置需求和格式.支持特性功能如下: 设置默认值 读取 JSON.TOML.Y ...

  7. Go 学习笔记(77)— Go 第三方库之 cronexpr(解析 crontab 表达式,定时任务)

    cronexpr 支持的比 Linux 自身的 crontab 更详细,可以精确到秒级别. ​ 1. 实现方式 cronexpr 表达式从前到后的顺序如下所示: 字段类型 是否为必须字段 允许的值 允 ...

  8. mybatis配置文件解析

    mybatis配置文件解析 mybatis核心配置文件`mybatis-config.xml文件. mybatis的配置文件包含了会深深影响mybatis行为的设置和属性信息. 能配置的内容: con ...

  9. 谷歌BERT预训练源码解析(二):模型构建

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/weixin_39470744/arti ...

最新文章

  1. 一个漂亮的 PlaceHolder
  2. UITableViewHeader 动态调整高度
  3. HDU_1075 What Are You Talking About(Trie 树)
  4. 切削为什么没有切屑_机械加工切削“断屑”的经验分享,老师傅来看看!
  5. java中strictfp么意思_什么时候应该在java中使用“strictfp”关键字?
  6. pta-4、运算符-找钱 (10 分)
  7. 计算机组成原理页表长度,计算机组成原理(2)-虚拟存储器
  8. 第十届中国开源黑客松等你来
  9. php有意思的小程序,这应该是迄今为止最全的小程序Top 100 榜单了,php中文网诚意奉上...
  10. 【读书笔记】金字塔原理-目录
  11. matlab printf格式化输出,如何使用 printf 来格式化输出
  12. 字符串函数-unquote()函数
  13. Android 自定义View
  14. 批处理命令之Start的详细用法-P处理打开IE窗口最大化
  15. Python猜数字小游戏
  16. STM32中的串口通信的基础知识
  17. Android瀑布流,类似于蘑菇街和迷尚 应用里的排列
  18. PWM整流器仿真模型 单位功率因数 matlab simulink
  19. MySQL-日志、备份与恢复
  20. 2.着色器(shader)

热门文章

  1. Spring-boot快速实现Spring框架配置
  2. Linux On ARM开发纪要
  3. 容器编排技术 -- Kubernetes入门概述
  4. Docker教程(一) Docker入门教程
  5. 深入理解Java虚拟机(第三版)-13.Java内存模型与线程
  6. HTML页面加载完毕后,再运行JS业务
  7. Linux debian 查看CPU温度
  8. C#LeetCode刷题之#171-Excel表列序号(Excel Sheet Column Number)
  9. 关于黑名单和白名单的一些思考
  10. 使用python编写自己的进程调试工具