c++ 用vector保存的点坐标值相互两两作比较,嵌套for循环实现了,但是效率不高,有什么方法可以提高效率,代码如下

mrmuto2 2015-06-20 03:24:17
算法的目的:坐标与其他坐标一一比较,如果两坐标距离相差小于3就保存为一组点,如下面点(110, 110)
和其他点一一比较(包括自己),结果是(110, 110)(110, 111)(110, 110)(110, 112),现在可以实现,但是
如果我的点有上万个,嵌套for循环效率太低了,有什么方法改写可以提高效率,之前考虑过hashmap,因为
以前元素查重用过可以实现而且很快,但是现在元素比较是找一个范围不是相同,好像hashmap用不了,有什么
好的方法吗


#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;

int main()
{

vector<Point> p;
vector<Point> temp;
vector<vector<Point> > centerbox;

p.push_back(Point(110, 110));
p.push_back(Point(110, 111));
p.push_back(Point(110, 110));
p.push_back(Point(110, 112));
p.push_back(Point(111, 112));
p.push_back(Point(150, 111));


for (vector<Point> ::iterator iter1 = p.begin(); iter1 != p.end(); ++iter1) {


for (vector<Point> ::iterator iter2 = p.begin(); iter2 != p.end();) {



if (abs((*iter1).x - (*iter2).x) + abs((*iter1).y - (*iter2).y) < 3) {

temp.push_back((*iter2));
++iter2;
}
else {
++iter2;
}
}


centerbox.push_back(temp);

temp.clear();

}

return 0;
}
...全文
1147 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2015-06-23
  • 打赏
  • 举报
回复
无profiler不要谈效率!!尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代!
zilaishuichina 2015-06-23
  • 打赏
  • 举报
回复
引用 8 楼 cjqpker 的回复:
[quote=引用 7 楼 zilaishuichina 的回复:] [quote=引用 6 楼 mrmuto2 的回复:] [quote=引用 4 楼 zilaishuichina 的回复:] 对于 你的筛选条件 :
if (abs((*iter1).x - (*iter2).x) + abs((*iter1).y - (*iter2).y) < 3)
我不知道,你的这个 3 , 这个条件是不是固定的。 如果是固定的, 那么一个点周围,按照你的条件,和它距离小于3的点, 最多也就 1+3+5+3+1 = 13 个点 也就是说, 当你取一个点(x,y)出来做判断的时候, 你只需要判断: 在(x-2,y) ,(x+2,y) ,(x,y-2),(x,y+2) 这个矩形区域的13个点(这其中还包括被判断的点自己,实际上就是周围12个点), 在不在你的所有点列表中,那么就算你有1万个点, 就是判断12万次, 而不是双重循环(1万×1万那得判断1亿次)
但是找每个点,进行相等比较不是还得跑一次完整的循环吗,然后13个点找是否存在,得13x1万,然后这个vector里每个元素都得去找,不就变成13x1万x1万了?[/quote] 你的所有点的列表, 你可以用一个map存,或者是hash,如果不是要求极致的效率,一般map的2份查找就可以了,

p.push_back(Point(110, 110));
    p.push_back(Point(110, 111));
    p.push_back(Point(110, 110));
    p.push_back(Point(110, 112));
    p.push_back(Point(111, 112));
    p.push_back(Point(150, 111));
变成

map<Point,Point> p
p[Point(110, 110)] = Point(110, 110);
p[Point(110, 111)] = Point(110, 111);
p[Point(150, 110)] = Point(150, 110);
...
对于任意一个点(x,y); 他的周围13个点都是: (x-2,y) (x-1,y-1),(x-1,y),(x-1,y+1) (x,y-2),(x,y-1), (x,y), (x,y+1), (x,y+2) (x+1,y-1),(x+1,y),(x+1,y+1) (x+2,y) 分别判断每个点 是否在上面的map<Point,Point> p中 [/quote] LZ的意思应该是在纠结这十三个点如何从数据结构中找出来。这取决于所有的点是如何存储的,如果是按照图像的点阵顺序存储的,就方便找这些点了,所以我觉得也可以从存储的结构上找出路 [/quote] 从map中找一个点是否存在,已经很快了, 2的13次方 = 8192,说明: 1万多个点,从map中判断一个点存不存在,最坏情况是2分搜13次就可以确定一个点是否在所有点列表 那么总时间就是: 判断每个点是否存在搜13次 × 周围12个点 × 1万个待判断的点 如果楼主觉得想把这13次再优化一下,那么就用位图好了,一个字节表示8个点:如下可以表示一个8×8的点阵 1表示有点,0表示没点 01000010 = 66 // 表示第0行第1列有点(0,1),第0行第6列有点(0,6) 10101000 = 168 // 表示第1行第0列有点(1,0),第1行第2列有点(1,2),第1行第4列有点(1,4) 00101010 = 42 // 表示第2行第2列有点(2,2),第2行第4列有点(2,4),第2行第6列有点(2,6) 10100010 // 依次类推 00101010 01001010 比如你的图像是1000×1000个点,那么位图的大小就是 bitmap[1000 / 8][1000] = 125KB的一个2维数组 对于任意一个点(x,y) (x<1000,y<1000),它在位图中对应的2进制位就是 :(bitmap[x/8][y] << (x%8)) &0x80 为0则表示没点,否则为有点。 这样你根据点坐标,可以直接位运算出来一个点是否存在,这个时间复杂度已经是O(1) 那么总时间就是: 周围12个点 × 1万个待判断的点
芥末的无奈 2015-06-23
  • 打赏
  • 举报
回复
楼主,需找最短距离的两个点算法上通常用分治,感觉楼主的要求和求最短距离有点类似。 贴个链接,楼主可以试着改改看 http://blog.csdn.net/bertzhang/article/details/7260509
mrmuto2 2015-06-23
  • 打赏
  • 举报
回复
引用 10 楼 zilaishuichina 的回复:
[quote=引用 8 楼 cjqpker 的回复:] [quote=引用 7 楼 zilaishuichina 的回复:] [quote=引用 6 楼 mrmuto2 的回复:] [quote=引用 4 楼 zilaishuichina 的回复:] 对于 你的筛选条件 :
if (abs((*iter1).x - (*iter2).x) + abs((*iter1).y - (*iter2).y) < 3)
我不知道,你的这个 3 , 这个条件是不是固定的。 如果是固定的, 那么一个点周围,按照你的条件,和它距离小于3的点, 最多也就 1+3+5+3+1 = 13 个点 也就是说, 当你取一个点(x,y)出来做判断的时候, 你只需要判断: 在(x-2,y) ,(x+2,y) ,(x,y-2),(x,y+2) 这个矩形区域的13个点(这其中还包括被判断的点自己,实际上就是周围12个点), 在不在你的所有点列表中,那么就算你有1万个点, 就是判断12万次, 而不是双重循环(1万×1万那得判断1亿次)
但是找每个点,进行相等比较不是还得跑一次完整的循环吗,然后13个点找是否存在,得13x1万,然后这个vector里每个元素都得去找,不就变成13x1万x1万了?[/quote] 你的所有点的列表, 你可以用一个map存,或者是hash,如果不是要求极致的效率,一般map的2份查找就可以了,

p.push_back(Point(110, 110));
    p.push_back(Point(110, 111));
    p.push_back(Point(110, 110));
    p.push_back(Point(110, 112));
    p.push_back(Point(111, 112));
    p.push_back(Point(150, 111));
变成

map<Point,Point> p
p[Point(110, 110)] = Point(110, 110);
p[Point(110, 111)] = Point(110, 111);
p[Point(150, 110)] = Point(150, 110);
...
对于任意一个点(x,y); 他的周围13个点都是: (x-2,y) (x-1,y-1),(x-1,y),(x-1,y+1) (x,y-2),(x,y-1), (x,y), (x,y+1), (x,y+2) (x+1,y-1),(x+1,y),(x+1,y+1) (x+2,y) 分别判断每个点 是否在上面的map<Point,Point> p中 [/quote] LZ的意思应该是在纠结这十三个点如何从数据结构中找出来。这取决于所有的点是如何存储的,如果是按照图像的点阵顺序存储的,就方便找这些点了,所以我觉得也可以从存储的结构上找出路 [/quote] 从map中找一个点是否存在,已经很快了, 2的13次方 = 8192,说明: 1万多个点,从map中判断一个点存不存在,最坏情况是2分搜13次就可以确定一个点是否在所有点列表 那么总时间就是: 判断每个点是否存在搜13次 × 周围12个点 × 1万个待判断的点 如果楼主觉得想把这13次再优化一下,那么就用位图好了,一个字节表示8个点:如下可以表示一个8×8的点阵 1表示有点,0表示没点 01000010 = 66 // 表示第0行第1列有点(0,1),第0行第6列有点(0,6) 10101000 = 168 // 表示第1行第0列有点(1,0),第1行第2列有点(1,2),第1行第4列有点(1,4) 00101010 = 42 // 表示第2行第2列有点(2,2),第2行第4列有点(2,4),第2行第6列有点(2,6) 10100010 // 依次类推 00101010 01001010 比如你的图像是1000×1000个点,那么位图的大小就是 bitmap[1000 / 8][1000] = 125KB的一个2维数组 对于任意一个点(x,y) (x<1000,y<1000),它在位图中对应的2进制位就是 :(bitmap[x/8][y] << (x%8)) &0x80 为0则表示没点,否则为有点。 这样你根据点坐标,可以直接位运算出来一个点是否存在,这个时间复杂度已经是O(1) 那么总时间就是: 周围12个点 × 1万个待判断的点 [/quote] 真的非常谢谢你们,我好好消化一下内容!!
mrmuto2 2015-06-22
  • 打赏
  • 举报
回复
引用 2 楼 cjqpker 的回复:
这种计算量,即使是上万个点,两层循环也不会消耗太多时间,如果点的数量大致上可以确定,使用数组就可以了,没必要使用vector。 另外,应该从算法上寻求突破,比如你这个需求,如果坐标点之间相差大于5,那就使用一种排序的数据结构(数组加快速并排序也可以),排序依据为(x+y)的和,在拿到一个点(假设是A)进行比较时,就可以用二分法取一个范围,这个范围的边界可以是(x+y)的和比A点的(x+y)大5,以及小5,这样在范围内进行比较,就比较快了。 不过我觉得,上万的数据,数组+两层循环应该足够了。
我是做图像处理用的,一张图片上千个点的话,跑起来要3s,这跑视频就不行了,vector应该和数组速度差不多吧,我想在算法上找改变,排序二分法的确是一种方法,但我我感觉排序就会很耗时,你认为呢?还有有什么好建议吗,谢谢你的回答
假正经的班长 2015-06-22
  • 打赏
  • 举报
回复
引用 7 楼 zilaishuichina 的回复:
[quote=引用 6 楼 mrmuto2 的回复:] [quote=引用 4 楼 zilaishuichina 的回复:] 对于 你的筛选条件 :
if (abs((*iter1).x - (*iter2).x) + abs((*iter1).y - (*iter2).y) < 3)
我不知道,你的这个 3 , 这个条件是不是固定的。 如果是固定的, 那么一个点周围,按照你的条件,和它距离小于3的点, 最多也就 1+3+5+3+1 = 13 个点 也就是说, 当你取一个点(x,y)出来做判断的时候, 你只需要判断: 在(x-2,y) ,(x+2,y) ,(x,y-2),(x,y+2) 这个矩形区域的13个点(这其中还包括被判断的点自己,实际上就是周围12个点), 在不在你的所有点列表中,那么就算你有1万个点, 就是判断12万次, 而不是双重循环(1万×1万那得判断1亿次)
但是找每个点,进行相等比较不是还得跑一次完整的循环吗,然后13个点找是否存在,得13x1万,然后这个vector里每个元素都得去找,不就变成13x1万x1万了?[/quote] 你的所有点的列表, 你可以用一个map存,或者是hash,如果不是要求极致的效率,一般map的2份查找就可以了,

p.push_back(Point(110, 110));
    p.push_back(Point(110, 111));
    p.push_back(Point(110, 110));
    p.push_back(Point(110, 112));
    p.push_back(Point(111, 112));
    p.push_back(Point(150, 111));
变成

map<Point,Point> p
p[Point(110, 110)] = Point(110, 110);
p[Point(110, 111)] = Point(110, 111);
p[Point(150, 110)] = Point(150, 110);
...
对于任意一个点(x,y); 他的周围13个点都是: (x-2,y) (x-1,y-1),(x-1,y),(x-1,y+1) (x,y-2),(x,y-1), (x,y), (x,y+1), (x,y+2) (x+1,y-1),(x+1,y),(x+1,y+1) (x+2,y) 分别判断每个点 是否在上面的map<Point,Point> p中 [/quote] LZ的意思应该是在纠结这十三个点如何从数据结构中找出来。这取决于所有的点是如何存储的,如果是按照图像的点阵顺序存储的,就方便找这些点了,所以我觉得也可以从存储的结构上找出路
zilaishuichina 2015-06-22
  • 打赏
  • 举报
回复
引用 6 楼 mrmuto2 的回复:
[quote=引用 4 楼 zilaishuichina 的回复:] 对于 你的筛选条件 :
if (abs((*iter1).x - (*iter2).x) + abs((*iter1).y - (*iter2).y) < 3)
我不知道,你的这个 3 , 这个条件是不是固定的。 如果是固定的, 那么一个点周围,按照你的条件,和它距离小于3的点, 最多也就 1+3+5+3+1 = 13 个点 也就是说, 当你取一个点(x,y)出来做判断的时候, 你只需要判断: 在(x-2,y) ,(x+2,y) ,(x,y-2),(x,y+2) 这个矩形区域的13个点(这其中还包括被判断的点自己,实际上就是周围12个点), 在不在你的所有点列表中,那么就算你有1万个点, 就是判断12万次, 而不是双重循环(1万×1万那得判断1亿次)
但是找每个点,进行相等比较不是还得跑一次完整的循环吗,然后13个点找是否存在,得13x1万,然后这个vector里每个元素都得去找,不就变成13x1万x1万了?[/quote] 你的所有点的列表, 你可以用一个map存,或者是hash,如果不是要求极致的效率,一般map的2份查找就可以了,

p.push_back(Point(110, 110));
    p.push_back(Point(110, 111));
    p.push_back(Point(110, 110));
    p.push_back(Point(110, 112));
    p.push_back(Point(111, 112));
    p.push_back(Point(150, 111));
变成

map<Point,Point> p
p[Point(110, 110)] = Point(110, 110);
p[Point(110, 111)] = Point(110, 111);
p[Point(150, 110)] = Point(150, 110);
...
对于任意一个点(x,y); 他的周围13个点都是: (x-2,y) (x-1,y-1),(x-1,y),(x-1,y+1) (x,y-2),(x,y-1), (x,y), (x,y+1), (x,y+2) (x+1,y-1),(x+1,y),(x+1,y+1) (x+2,y) 分别判断每个点 是否在上面的map<Point,Point> p中
mrmuto2 2015-06-22
  • 打赏
  • 举报
回复
引用 4 楼 zilaishuichina 的回复:
对于 你的筛选条件 :
if (abs((*iter1).x - (*iter2).x) + abs((*iter1).y - (*iter2).y) < 3)
我不知道,你的这个 3 , 这个条件是不是固定的。 如果是固定的, 那么一个点周围,按照你的条件,和它距离小于3的点, 最多也就 1+3+5+3+1 = 13 个点 也就是说, 当你取一个点(x,y)出来做判断的时候, 你只需要判断: 在(x-2,y) ,(x+2,y) ,(x,y-2),(x,y+2) 这个矩形区域的13个点(这其中还包括被判断的点自己,实际上就是周围12个点), 在不在你的所有点列表中,那么就算你有1万个点, 就是判断12万次, 而不是双重循环(1万×1万那得判断1亿次)
但是找每个点,进行相等比较不是还得跑一次完整的循环吗,然后13个点找是否存在,得13x1万,然后这个vector里每个元素都得去找,不就变成13x1万x1万了?
mrmuto2 2015-06-22
  • 打赏
  • 举报
回复
引用 4 楼 zilaishuichina 的回复:
对于 你的筛选条件 :
if (abs((*iter1).x - (*iter2).x) + abs((*iter1).y - (*iter2).y) < 3)
我不知道,你的这个 3 , 这个条件是不是固定的。 如果是固定的, 那么一个点周围,按照你的条件,和它距离小于3的点, 最多也就 1+3+5+3+1 = 13 个点 也就是说, 当你取一个点(x,y)出来做判断的时候, 你只需要判断: 在(x-2,y) ,(x+2,y) ,(x,y-2),(x,y+2) 这个矩形区域的13个点(这其中还包括被判断的点自己,实际上就是周围12个点), 在不在你的所有点列表中,那么就算你有1万个点, 就是判断12万次, 而不是双重循环(1万×1万那得判断1亿次)
是固定的,但是你说的是怎么实现?所有点都保存在一个vector里面了,我怎么找出13个点的区域在哪里?能简单说明一下吗? 或者能把代码简单写出来吗?你的想法的确给了我启发,真是谢谢你
zilaishuichina 2015-06-22
  • 打赏
  • 举报
回复
对于 你的筛选条件 :
if (abs((*iter1).x - (*iter2).x) + abs((*iter1).y - (*iter2).y) < 3)
我不知道,你的这个 3 , 这个条件是不是固定的。 如果是固定的, 那么一个点周围,按照你的条件,和它距离小于3的点, 最多也就 1+3+5+3+1 = 13 个点 也就是说, 当你取一个点(x,y)出来做判断的时候, 你只需要判断: 在(x-2,y) ,(x+2,y) ,(x,y-2),(x,y+2) 这个矩形区域的13个点(这其中还包括被判断的点自己,实际上就是周围12个点), 在不在你的所有点列表中,那么就算你有1万个点, 就是判断12万次, 而不是双重循环(1万×1万那得判断1亿次)
假正经的班长 2015-06-21
  • 打赏
  • 举报
回复
这种计算量,即使是上万个点,两层循环也不会消耗太多时间,如果点的数量大致上可以确定,使用数组就可以了,没必要使用vector。 另外,应该从算法上寻求突破,比如你这个需求,如果坐标点之间相差大于5,那就使用一种排序的数据结构(数组加快速并排序也可以),排序依据为(x+y)的和,在拿到一个点(假设是A)进行比较时,就可以用二分法取一个范围,这个范围的边界可以是(x+y)的和比A点的(x+y)大5,以及小5,这样在范围内进行比较,就比较快了。 不过我觉得,上万的数据,数组+两层循环应该足够了。
mrmuto2 2015-06-21
  • 打赏
  • 举报
回复
没人懂吗?求指教

65,208

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧