Make a map of the "regions", basically std::map<coordinates/len, std::vector<point>> . Add each point to this region and each of the 8 neighboring O(N*logN) regions O(N*logN) . Run the "nieve" algorithm in each of these smaller lists (technically O(N^2) , if theres maximum density, then it becomes O(N*density) ). Finally: in your source list, iterate through each point , and if it was removed from any of the 8 mini-lists, it was inserted, remove it from the list. O(n)
Without density restrictions, it is O(N^2) and slow. But it gets faster and faster as the dots are more common. If the points are somewhat evenly distributed on a known boundary, you can switch to a two-dimensional array, which will greatly accelerate it, and if there is a constant density limit, this technically does this O(n) algorithm.
So you sort the list of two variables. The grid / map / 2dvector element.
[EDIT] You mentioned that you also have problems with the "nieve" method, so here's what:
template<class iterator, class criterion> iterator RemoveCriterion(iterator begin, iterator end, criterion criter) { iterator actend = end; for(iterator L=begin; L != actend; ++L) { iterator R(L); for(++R; R != actend;) { if (criter(*L, *R) { iterator N(R); std::rotate(R, ++N, actend); --actend; } else ++R; } } return actend; }
This should work with linked lists, vectors and similar containers and work in reverse order. Unfortunately, this is a bit slow due to the fact that linked list properties are not taken into account. It is possible to make much faster versions that work only with linked lists in a certain direction. Note that the return value is important, like other mutation algorithms. It can modify the contents of the container, not the container itself, so you will need to delete all the elements after the return value when it ends.