免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 太平绅士
打印 上一主题 下一主题

求解一个空间位置的算法 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2009-03-27 10:56 |只看该作者
原帖由 windyrobin 于 2009-3-27 10:43 发表
貌似是线段树问题,用扫描方法...
呵呵,好久不玩这类复杂算法料,绅士可查下相关资料。


哈哈, 多谢~
理解了...
考虑重点不在重叠, 在于顶点坐标.
利用顶点坐标, 将空间看成一些线段, 然后利用树, 查找, 插入/删除的动作. 可以得到log N的复杂度.
我想那么复杂, 不及您一句 "线段树", 感谢!

论坛徽章:
0
12 [报告]
发表于 2009-03-27 10:56 |只看该作者
原帖由 太平绅士 于 2009-3-27 10:34 发表


只是自己在写个窗口类,弄着玩。判定窗口的位置。



绅士肯定是在骗人,哪个系统的窗口也不能有成千上万个,
桌面系统的几个窗口,遍历就ok料

论坛徽章:
1
天秤座
日期:2014-04-27 07:42:20
13 [报告]
发表于 2009-03-27 11:12 |只看该作者
假设空间原点坐标0,0,0.某点坐标10,10,10.那么就只有两种情况,最靠近原点的顶点坐标是否有某个值小于某点坐标的对应坐标值,离原点最远的顶点是否否有某个值大于某点坐标的对应坐标值.任何一个符合就是包含了

论坛徽章:
0
14 [报告]
发表于 2009-03-27 11:17 |只看该作者
游戏可能有这个需求。模拟计算什么?

论坛徽章:
0
15 [报告]
发表于 2009-03-27 11:25 |只看该作者
原帖由 A.com 于 2009-3-27 11:12 发表
假设空间原点坐标0,0,0.某点坐标10,10,10.那么就只有两种情况,最靠近原点的顶点坐标是否有某个值小于某点坐标的对应坐标值,离原点最远的顶点是否否有某个值大于某点坐标的对应坐标值.任何一个符合就是包含了:mr ...


论坛徽章:
0
16 [报告]
发表于 2009-03-27 11:29 |只看该作者
原帖由 prolj 于 2009-3-27 11:17 发表
游戏可能有这个需求。模拟计算什么?

原帖由 windyrobin 于 2009-3-27 10:56 发表
绅士肯定是在骗人,哪个系统的窗口也不能有成千上万个,
桌面系统的几个窗口,遍历就ok料


不骗你们, 这是鄙人的娱乐, 过渡设计也是娱乐.

论坛徽章:
0
17 [报告]
发表于 2009-03-28 00:09 |只看该作者
报告一下结果:
利用 std::map 实现的线段树, 在线段数量为10000的量级上,
线段树的方法, 始终和直接全部遍历查找结果的方法, 时间上不相上下.

再高的数量级上, 构造线段树的时间花费太久了, 明显不适用.

功夫白花了.

论坛徽章:
0
18 [报告]
发表于 2009-03-28 10:26 |只看该作者
原帖由 A.com 于 2009-3-27 11:12 发表
假设空间原点坐标0,0,0.某点坐标10,10,10.那么就只有两种情况,最靠近原点的顶点坐标是否有某个值小于某点坐标的对应坐标值,离原点最远的顶点是否否有某个值大于某点坐标的对应坐标值.任何一个符合就是包含了:mr ...

方法正点。。。

论坛徽章:
0
19 [报告]
发表于 2009-03-28 15:18 |只看该作者
原帖由 太平绅士 于 2009-3-28 00:09 发表
报告一下结果:
利用 std::map 实现的线段树, 在线段数量为10000的量级上,
线段树的方法, 始终和直接全部遍历查找结果的方法, 时间上不相上下.

再高的数量级上, 构造线段树的时间花费太久了, 明显不适用.
...

不清楚你的map怎么用的呵 ,以前都是自己构造线段树 ,根本不用stl的--它太慢了,
这是典型的线段树+离散化,用扫描方法完成,也可以用虚二叉树搞定以避免动态内存分配
和 “数量为10000” 没多大关系,虚二叉树构造时间是o(4n),修改操作为o(lgn),呵呵
肯定是你对线段树理解有误,可搜下相关的论文.

[ 本帖最后由 windyrobin 于 2009-3-28 15:19 编辑 ]

论坛徽章:
0
20 [报告]
发表于 2009-03-29 13:42 |只看该作者
复习了下算法 ,搞到凌晨2点,写了个简陋的线段树
测试发现, 在我提供的例子中,速度是普通版的1. 8倍 左右,
我用vector存储 window id , 添加、删除修改操做比较低效,
换成set 应该能大幅提高修改操作效率,可这样会影响到查询效率,
因为相比与vector ,set的遍历很耗时的。
vc 2008 ,release

  1. #include <set>
  2. #include <vector>
  3. using namespace std;

  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <time.h>
  7. #include <windows.h>

  8. #define  MAX(a ,b) ((a)>(b)?(a):(b))
  9. #define  MIN(a ,b) ((a)<(b)?(a):(b))


  10. /*分辨率*/
  11. #define  MAX_WIDTH 1024
  12. #define  MAX_HEIGHT 768

  13. /*窗口数目*/
  14. #define  WINDOW_CNT  1000000

  15. /*鼠标点击 测试次数*/
  16. #define  CLICK_CNT 100

  17. struct window{
  18.         int id;
  19.         int ltX ;//left top x
  20.         int ltY;
  21.         int rbX;//right bottom x;
  22.         int rbY;
  23. }windows[WINDOW_CNT];

  24. /*待测鼠标点击数组*/
  25. struct click{
  26.         int posX;
  27.         int posY;
  28. }clicks[CLICK_CNT];

  29. typedef struct{
  30.         int left;
  31.         int right;
  32.         vector<int> windowSet;
  33.         int color;/*if it has childs ,set if to 1*/
  34. }node;

  35. /*width and height v-binary-tree*/
  36. node treeRoot[MAX_WIDTH * 4 + 1];

  37. void set_left_right(node *head ,int pos ,int left ,int right)
  38. {
  39.         head[pos].left = left ;
  40.         head[pos].right = right;
  41.         head[pos].color =0;
  42.         if(left == right) return;
  43.         /*else set childs*/
  44.         int middle = (left +right)>>1;
  45.         int lChild = pos<<1;
  46.         set_left_right(head  ,lChild ,left ,middle);
  47.         set_left_right(head  ,++lChild ,++middle ,right);
  48. }

  49. void addNode(node *head ,int nodePos ,int windowId ,int lPos ,int rPos)
  50. {
  51.         int left = head[nodePos].left;
  52.         int right =head[nodePos].right;
  53.         int middle = (left+right)>>1;
  54.         int lChild = nodePos<<1;

  55.         if(lPos ==left && rPos == right){
  56.                 head[nodePos].windowSet.push_back(windowId);
  57.                 return ;
  58.         }
  59.         /*else set color flag*/
  60.         head[nodePos].color = 1;
  61.         if(middle >= rPos){
  62.                 addNode(head ,lChild  ,windowId ,lPos ,rPos);
  63.         }else if(middle < lPos){
  64.                 addNode(head ,++lChild,windowId ,lPos ,rPos);
  65.         }else{
  66.                 addNode(head ,lChild ,windowId ,lPos ,middle);
  67.                 addNode(head ,++lChild ,windowId ,++middle ,rPos);
  68.         }
  69. }

  70. void mapWindow2Tree()
  71. {
  72.         window *pw = NULL;
  73.         for(int i=0 ;i<WINDOW_CNT ;++i){
  74.                 pw =windows + i;
  75.                 addNode(treeRoot ,1 ,pw->id ,pw->ltX ,pw->rbX);
  76.         }
  77. }

  78. void init()
  79. {
  80.         int i;
  81.         srand(time(0));
  82.         for(i=0 ;i<WINDOW_CNT ;++i){
  83.                 windows[i].id = i;
  84.                 windows[i].ltX = rand()%MAX_WIDTH;
  85.                 windows[i].ltY = rand()%MAX_HEIGHT;
  86.                 windows[i].rbX = rand()%MAX_WIDTH;
  87.                 windows[i].rbY = rand()%MAX_HEIGHT;

  88.                 windows[i].ltX = MIN(windows[i].ltX ,windows[i].rbX);
  89.                 windows[i].rbX = MAX(windows[i].ltX ,windows[i].rbX);
  90.                 windows[i].ltY = MIN(windows[i].ltY ,windows[i].rbY);
  91.                 windows[i].rbY = MAX(windows[i].ltY ,windows[i].rbY);
  92.         }
  93.         for(i=0 ;i<CLICK_CNT ;++i){
  94.                 clicks[i].posX = rand()%MAX_WIDTH;
  95.                 clicks[i].posY = rand()%MAX_HEIGHT;
  96.         }
  97.         set_left_right(treeRoot ,1 ,0 ,MAX_WIDTH-1);
  98.         mapWindow2Tree();
  99. }


  100. void printClicks()
  101. {
  102.         for(int i=0 ;i<CLICK_CNT ;++i){
  103.                 printf("%d\t%d\n" ,clicks[i].posX ,clicks[i].posY);
  104.         }
  105. }

  106. static int resultCnt;
  107. static int results[WINDOW_CNT];
  108. static int chksize;
  109. void recur_find(node* head ,int nodePos ,click *event)
  110. {
  111.         node *pNode = head + nodePos;
  112.         window *pw = NULL;
  113.        
  114.         vector<int> &ws = pNode->windowSet;
  115.         int vSize = ws.size();
  116.         for(int i=0 ;i<vSize ;++i){
  117.                 pw = windows + ws[i];
  118.                 if(pw->ltY<= event->posY && pw->rbY >=event->posY)
  119.                         ++resultCnt;
  120.         }
  121.         chksize += pNode->windowSet.size();
  122.         if(pNode->color != 0 && pNode->left<pNode->right){
  123.                 int lChild = nodePos<<1;
  124.                 int middle = (pNode->left + pNode->right)>>1;
  125.                 if(event->posX <= middle){
  126.                         recur_find(head ,lChild ,event);
  127.                 }else{
  128.                         recur_find(head ,++lChild ,event);
  129.                 }
  130.         }
  131. }

  132. void click_find(click *event)
  133. {
  134.         recur_find(treeRoot ,1 ,event);
  135. }

  136. static int allCnt ;

  137. void vtree_find()
  138. {
  139.         allCnt =0;
  140.         chksize = 0;
  141.         for(int i=0 ;i<CLICK_CNT ;++i){
  142.                 resultCnt = 0;
  143.                 click_find(clicks + i);
  144.                 allCnt += resultCnt;
  145.         }
  146.         printf("allCnt : %d ave chk : %d\n" ,allCnt ,chksize/CLICK_CNT);
  147. }

  148. void iter_find()
  149. {
  150.         allCnt =0;
  151.         window *pw = NULL;
  152.         click *ck = NULL;
  153.         for(int i=0 ;i<CLICK_CNT ;++i){
  154.                 ck = clicks + i;
  155.                 for(int j=0 ;j<WINDOW_CNT ;++j){
  156.                         pw = windows + j;
  157.                         if(pw->ltX <= ck->posX && pw->rbX >=ck->posX && pw->ltY<=ck->posY && pw->rbY >=ck->posY)
  158.                                 ++allCnt;
  159.                 }
  160.         }
  161.         printf("allCnt : %d\n" ,allCnt);
  162. }

  163. long timeCal(void (*f)())
  164. {
  165.         long beginTime = GetTickCount();
  166.         f();
  167.         long endTime = GetTickCount();
  168.         return endTime - beginTime;
  169. }

  170. void timeTest()
  171. {
  172.         printf("\nvtree find :\n");
  173.         for(int i=0;i<10 ;i++){
  174.                 printf("%d " ,timeCal(vtree_find));
  175.         }
  176.         printf("\niter find :\n");
  177.         for(int i=0 ;i<10 ;i++){
  178.                 printf("%d " ,timeCal(iter_find));
  179.         }
  180. }

  181. int main()
  182. {
  183.         init();
  184.         //printClicks();

  185.         timeTest();

  186.         system("pause");
  187.        
  188.         return 0;
  189. }
复制代码

[ 本帖最后由 windyrobin 于 2009-3-29 13:44 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP