1. 引入

最近在参加学校的计算机仿真大赛,时间好像有点不够,所以只完成了前面的一部分最基础的功能,中途还是选择了放弃。但是之前的部分的确觉得完成得还不错,在这里分享一下。题目是要完成一个宇宙飞船加油点的分配调度系统。完成的部分是给定坐标附近点的搜索。

2. 算法使用原因

我们要完成的一个是二维附近点搜索的算法。就是在给出若干个加油点的二维坐标,然后再给你一个当前坐标,你要搜索出距离当前坐标最近的一个加油站的坐标点。在考虑二维的附近点搜索时,最原始的方法肯定是将所有的加油点的坐标都加入到list中.然后遍历所有的节点,判断哪个节点的坐标距离自己最近。但是这样操作的话,由于我们要进行多次的附近点搜索,这样每次搜索的成本就会相当大,比如我们搜索 N次,一共有 M 个加油点,复杂度将达到 N*M ,降低搜索效率。

所以我们应该降低每次的搜索效率。然后想过要使用建立哈希表进行搜索,这样成本基本花在了建表上,搜索所花费的时间就会少很多。但是按照自己的想法,去建一个哈希表的确比较困难,而且当地图比较大时,空间复杂度会十分的高,因此这种方法还是需要改进。然后我查阅了一些资料,参阅到一些附近点搜索的经典算法,也就是将要介绍的GeoHash算法。能够将坐标变成特定的编码,然后进行对应哈希,还能够根据编码的前缀,来进行判断两点是否在附近。

3. 算法介绍

在一篇很经典的文章中有所介绍GeoHash下附链接:

http://blog.nosqlfan.com/html/1811.html

此博客中,简要地说明GeoHash算法的思想:

  1. 将地图四分,也就是分成左上、右上、左下、右下四个部分,然后对应的地图块的编码后面追加"01","11","00","10"

    |01|11|

    |---|---|

    |00|10|
  2. 然后再将四分后的各个地图块,重复步骤1,不断地进行四分,编码也会两位两位地进行增加。直到地图块不能再进行四分。
  3. 得到对应的每个坐标的编码。

这就是GeoHash最基础的算法,能够将地图上的每个坐标点都进行编码。然后根据这些编码,很快就可以发现一个规律,因为是按着每个地图4分的,所以这地图四分前的编码是相同的,即使4分之后,这4块地图还是有着相同的前缀,因此,我们可以根据编码的最长相同前缀,去找出距离最近的加油站的坐标。

但是!这个算法还是有很大的缺点的:

由于GeoHash是将区域划分为一个个规则矩形,并对每个矩形进行编码,会导致以下问题,比如红色的点是我们的位置,绿色的两个点分别是附近的两加油点,但是在查询的时候会发现距离较远加油站的GeoHash编码与我们一样(因为在同一个GeoHash区域块上),而较近加油站的GeoHash编码与我们不一致。这个问题往往产生在边界处。



因此,我们需要对算法进行改进,解决的思路很简单,我们查询时,除了使用定位点的GeoHash编码进行匹配外,还使用周围8个区域的GeoHash编码,这样可以避免这个问题。

4. 需要解决的问题

  1. 坐标值转化为GeoHash编码值
  2. 根据当前区域的GeoHash,推算出周围8个方位区域块的的GeoHash值。
  3. 将这8个区域块中所有加油点进行储存,并且一一计算它们到当前坐标的距离,并且计算出最短距离的点。
  4. 考虑存储结构,以及算法实现。

5. 算法实现

因为项目开发的时候要可视化,所以当时就选择了使用C#。接下来的实现代码,都是C#编写的。

1. 坐标值转化为GeoHash

首先我们要知道当前地图大小为多少,取横坐标、纵坐标的中值,然后区分出4个区域,然后按照坐标所落到的区域,将对应的两位编号追加到地图的编码后,然后再将当前地图横坐标、纵坐标、都除以二,加上根据分块后地图改变的编号,以及坐标改变值,作为参数继续递归。递归结束的条件为地图的精度都已经减少为1的坐标的。

以下为实现代码:

  1. //xb,yb分别为地图的横坐标和总坐标大小
  2. //a,b,分别为给定点的横坐标、以及纵坐标
  3. //code,为存储编码的字符串
  4. public static void Encode(StringBuilder code, int xb, int yb, int a, int b)
  5. {
  6. if (xb == 1 && yb == 1)
  7. return;
  8. if (a < xb / 2 && b < yb / 2)
  9. {
  10. code.Append("00");
  11. Encode(code, xb / 2, yb / 2, a, b);
  12. }
  13. else if (a < xb / 2 && b >= yb / 2)
  14. {
  15. code.Append("01");
  16. Encode(code, xb / 2, yb / 2, a, b - yb / 2);
  17. }
  18. else if (a >= xb / 2 && b < yb / 2)
  19. {
  20. code.Append("10");
  21. Encode(code, xb / 2, yb / 2, a - xb / 2, b);
  22. }
  23. else if (a >= xb / 2 && b >= yb / 2)
  24. {
  25. code.Append("11");
  26. Encode(code, xb / 2, yb / 2, a - xb / 2, b - yb / 2);
  27. }
  28. return;
  29. }

2. 根据当前的编码,计算其余8个方位的编码

这个的实现其实也很简单。首先,我们其实先只需要搜寻实现上下左右4个方位的编码,那么根据一些小组合,剩下的8个方位,也同样能够计算得到了。

那么我们就要计算4个方位毗邻的编码。情况其实也很简单。

有一些区域的上级区域,与自己并不相同,因此前缀也肯定不相同。所以我们判断到上级区域不相同时,就要进行对上级区域的转变。但是要对上级区域进行改变的时候,发现上级的上级区域也不同,那又要再深一层地去改变。这样一直下去,就会同样形成一个递归的过程。用语言很那解释,但是大家把各个坐标的编码表都计算出来并且显示后,就很容易能够找到规律。

下面贴上代码供大家参考。

  1. public static void FindRight(StringBuilder code, int len)
  2. {
  3. if (len <= 0)
  4. return;
  5. if (code[len - 2] == '1')
  6. {
  7. FindRight(code, len - 2);
  8. code[len - 2] = '0';
  9. }
  10. else
  11. {
  12. code[len - 2] = '1';
  13. }
  14. return;
  15. }
  16. public static void FindLeft(StringBuilder code, int len)
  17. {
  18. if (len <= 0)
  19. return;
  20. if (code[len - 2] == '0')
  21. {
  22. FindLeft(code, len - 2);
  23. code[len - 2] = '1';
  24. }
  25. else
  26. {
  27. code[len - 2] = '0';
  28. }
  29. return;
  30. }
  31. public static void FindDown(StringBuilder code, int len)
  32. {
  33. if (len <= 0)
  34. return;
  35. if (code[len - 1] == '1')
  36. {
  37. FindDown(code, len - 2);
  38. code[len - 1] = '0';
  39. }
  40. else
  41. {
  42. code[len - 1] = '1';
  43. }
  44. return;
  45. }
  46. public static void Findup(StringBuilder code, int len)
  47. {
  48. if (len <= 0)
  49. return;
  50. if (code[len - 1] == '0')
  51. {
  52. Findup(code, len - 2);
  53. code[len - 1] = '1';
  54. }
  55. else
  56. {
  57. code[len - 1] = '0';
  58. }
  59. return;
  60. }

基于GeoHash算法的附近点搜索实现(一)的更多相关文章

  1. 程序员编程艺术第三十六~三十七章、搜索智能提示suggestion,附近点搜索

    第三十六~三十七章.搜索智能提示suggestion,附近地点搜索 作者:July.致谢:caopengcs.胡果果.时间:二零一三年九月七日. 题记 写博的近三年,整理了太多太多的笔试面试题,如微软 ...

  2. NASH:基于丰富网络态射和爬山算法的神经网络架构搜索 | ICLR 2018

    论文提出NASH方法来进行神经网络结构搜索,核心思想与之前的EAS方法类似,使用网络态射来生成一系列效果一致且继承权重的复杂子网,本文的网络态射更丰富,而且仅需要简单的爬山算法辅助就可以完成搜索,耗时 ...

  3. 故障定位之查找附近点GeoHash研讨

    随着移动终端的普及,很多应用都基于LBS功能,附近的某某(餐馆.银行.妹纸等等). 基础数据中,一般保存了目标位置的经纬度:利用用户提供的经纬度,进行对比,从而获得是否在附近. 目标:查找附近的XXX ...

  4. 基于改进人工蜂群算法的K均值聚类算法(附MATLAB版源代码)

    其实一直以来也没有准备在园子里发这样的文章,相对来说,算法改进放在园子里还是会稍稍显得格格不入.但是最近邮箱收到的几封邮件让我觉得有必要通过我的博客把过去做过的东西分享出去更给更多需要的人.从论文刊登 ...

  5. CARS: 华为提出基于进化算法和权值共享的神经网络结构搜索,CIFAR-10上仅需单卡半天 | CVPR 2020

    为了优化进化算法在神经网络结构搜索时候选网络训练过长的问题,参考ENAS和NSGA-III,论文提出连续进化结构搜索方法(continuous evolution architecture searc ...

  6. 查找附近网点geohash算法及实现 (Java版本号)

    參考文档: http://blog.csdn.net/wangxiafghj/article/details/9014363geohash  算法原理及实现方式 http://blog.charlee ...

  7. geohash算法原理及实现方式

    1.geohash特点 2.geohash原理 3.geohash的php .python.java.C#实现代码 4.观点讨论 w微博:http://weibo.com/dxl0321 geohas ...

  8. geohash 算法原理及实现方式

    转自:http://www.cnblogs.com/dengxinglin/archive/2012/12/14/2817761.html geohash 算法原理及实现方式 1.geohash 特点 ...

  9. 【智能算法】迭代局部搜索(Iterated Local Search, ILS)详解

    迭代局部搜索(Iterated Local Search, ILS) 源代码下载请关注微信公众号[程序猿声],在后台回复:[ILS],不包括[]即可下载. 00 目录 局部搜索算法 简单局部搜索 迭代 ...

随机推荐

  1. cocos2d-x物业现场

    pushScene()和popScene()用法: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMTYyNjY3MTc=/font/5a6L5L2 ...

  2. C++-传值与传引用的差别

    //值传递与引用传递的差别 #include <iostream> #include <iomanip> using namespace std; void fiddle(in ...

  3. SQL注入问题

    斌斌 (给我写信) 原创博文(http://blog.csdn.net/binbinxyz),转载请注明出处! 背景:对于ibaits参数引用可以使用#和$两种写法,其中#写法会采用预编译方式,将转义 ...

  4. 询url包括字符串参数(js高度注意事项)

    以防万一  url="http://write.blog.csdn.net/postedit? id=5&search=ok" function getArgs() { v ...

  5. 性能是全新的 SEO

    作为一个前端project师,那不只就是公开地处理那些美丽的html5, css3 和javascript特效.小而重要的一部分工作就是要让项目朝着代码稳定和代码标准方向进展.设计.信息结构以及后台限 ...

  6. 动态Lambda进阶一

    直接上代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; using S ...

  7. linux下&quot;=&quot;号与&quot;==&quot;号

    <鸟哥的linux私房菜>基础学习篇P382中说,在bash中"="与"=="是同样的,都代表推断是否相等,仅仅只是因为其它语言一般写法使用&quo ...

  8. MVC 检测用户是否登录

         当我们访问一个网站的需求检測用户是否已经登录(通过Session是否为null),我们知道在WebForm中能够定义一个BasePage类让他继承System.Web.UI.Page,重写它 ...

  9. 【程序员联盟】官网上线啦!coderunity.com

    内容简介 欢天喜地,[程序员联盟]官网上线咯(此处应该有鸡蛋丢过来...) [程序员联盟]官网 大家也许会问:“这几天小编都没出文章,跑哪里happy去啦?是不是偷懒去了?” 小编:“臣妾冤枉啊.” ...

  10. WPF技术触屏上的应用系列(四): 3D效果图片播放器(图片立体轮放、图片立体轮播、图片倒影立体滚动)效果实现

    原文:WPF技术触屏上的应用系列(四): 3D效果图片播放器(图片立体轮放.图片立体轮播.图片倒影立体滚动)效果实现 去年某客户单位要做个大屏触屏应用,要对档案资源进行展示之用.客户端是Window7 ...