I have a program that create graphs as shown below
The algorithm starts at the green color node and traverses the graph. Assume that a node (Linked list type node with 4 references Left, Right, Up and Down) has been added to the graph depicted by the red dot in the image. Inorder to integrate the newly created node with it neighbors I need to find the four objects and link it so the graph connectivity will be preserved.
Following is what I need to clarify
Assume that all yellow colored nodes are null and I do not keep a another data structure to map nodes what is the most efficient way to find the existence of the neighbors of the newly created node. I know the basic graph search algorithms like DFS, BFS etc and shortest path algorithms but I do not think any of these are efficient enough because the graph can have about 10000 nodes and doing graph search algorithms (starting from the green node) to find the neighbors when a new node is added seems computationally expensive to me.
If the graph search is not avoidable what is the best alternative structure. I thought of a large multi-dimensional array. However, this has memory wastage and also has the issue of not having negative indexes. Since the graph in the image can grow in any directions. My solution to this is to write a separate class that consists of a array based data structure to portray negative indexes. However, before taking this option I would like to know if I could still solve the problem without resolving to a new structure and save a lot of rework.
Thank you for any feedback and reading this question.
I'm not sure if I understand you correctly. Do you want to
Check that there is a path from (0,0) to (x1,y1)
or
Check if any of the neighbors of (x1,y1) are in the graph? (even if there is no path from (0,0) to any of this neighbors).
I assume that you are looking for a path (otherwise you won't use a linked-list), which implies that you can't store points which have no path to (0,0).
Also, you mentioned that you don't want to use any other data structure beside / instead of your 2D linked-list.
You can't avoid full graph search. BFS and DFS are the classic algorithms. I don't think that you care about the shortest path - any path would do.
Another approaches you may consider is A* (simple explanation here) or one of its variants (look here).
An alternative data structure would be a set of nodes (each node is a pair < x,y > of course). You can easily run 4 checks to see if any of its neighbors are already in the set. It would take O(n) space and O(logn) time for both check and add. If your programming language does not support pairs as nodes of a set, you can use a single integer (x*(Ymax+1) + Y) instead.
Your data structure can be made to work, but probably not efficiently. And it will be a lot of work.
With your current data structure you can use an A* search (see https://en.wikipedia.org/wiki/A*_search_algorithm for a basic description) to find a path to the point, which necessarily finds a neighbor. Then pretend that you've got a little guy at that point, put his right hand on the wall, then have him find his way clockwise around the point. When he gets back, he'll have found the rest.
What do I mean by find his way clockwise? For example suppose that you go Down from the neighbor to get to his point. Then your guy should be faced the first of Right, Up, and Left which he has a neighbor. If he can go Right, he will, then he will try the directions Down, Right, Up, and Left. (Just imagine trying to walk through the maze yourself with your right hand on the wall.)
This way lies insanity.
Here are two alternative data structures that are much easier to work with.
You can use a quadtree. See http://en.wikipedia.org/wiki/Quadtree for a description. With this inserting a node is logarithmic in time. Finding neighbors is also logarithmic. And you're only using space for the data you have, so even if your graph is very spread out this is memory efficient.
Alternately you can create a class for a type of array that takes both positive and negative indices. Then one that builds on that to be 2-d class that takes both positive and negative indices. Under the hood that class would be implemented as a regular array and an offset. So an array that can start at some number, positive or negative. If ever you try to insert a piece of data that is before the offset, you create a new offset that is below that piece by a fixed fraction of the length of the array, create a new array, and copy data from the old to the new. Now insert/finding neighbors are usually O(1) but it can be very wasteful of memory.
You can use a spatial index like a quad tree or a r-tree.
Related
I have a list of coordinates and I need to find the closest coordinate to a specific point which I'll call P.
At first I tried to just calculate the distance from each coordinate to P, but this is too slow.
I then tried to store these coordinates as a quad-tree, find the leaf node that contains P, then find the closest coordinate in that leaf by comparing distances of every coordinate to P. This gives a good approximation for the closest coordinate, but can be wrong sometimes. (when a coordinate is outside the leaf node, but closer). I've also tried searching through the leaf node's parent, but while that makes the search more accurate, it doesn't make it perfect.
If it is possible for this to be done with a quad-tree, please let me know how, otherwise, what other methods/data structures could I used that are reasonably efficient, or is it even possible to do this perfectly in an efficient manner?
Try "loose quadtree". It does not have a fixed volume per node. So it can adjust each node's bounding volume to adapt to the items added.
If you don't like quadtree's traversing performance and if your objects are just points, adaptive-grid can perform fast or very close to O(N). But memory-wise, loose quadtree would be better.
There is an algorithm by Hjaltason and Samet described in their paper "Distance browsing in spatial databases". It can easily be applied to quadtrees, I have an implementation here.
Basically, you maintain a sorted list of object, the list is sorted by distance (closest first), and the objects are either point in your tree (you call the coordinates) or nodes in the tree (distance to closest corner, or distance=0 if they overlap with you search point).
You start adding all nodes that overlap with your search point, and add all points and subnodes in these points.
Then you simply return points from the top of the list until you have as many closest points as you want. If a node is at the top of the list, add points/subnodes from that node to the list and check the top of the list again. Repeat.
yes you can find the closest coordinate inside a quad-tree even when it is not directly inside the leaf. in order to do that, you can do the following search algorithm :
search the closest position inside the quad-tree.
take its distance from your initial position
search all the nodes inside this bounding box from your root node
return the closest node from all the nodes inside this bounding box
however, this is a very basic algorithm with no performance optimizations. among other things :
if the distance calculated in 2. is less than the distance to the border of the tree node, then you don't need to do 3 or 4. (or you can take a node that is not the root node)
also, 3 and 4 could be simplified into a single algorithm that only search inside the tree with the distance to the closest node as the bounding box.
And you could also sort the way you search for the nodes inside the bounding box by beginning to search for the nodes closest to your position first.
However, I have not made complexity calculation, but you should expect a worst case scenario on one node that is as bad if not worst than normal, but in general you should get a pretty decent speed up all the while being error free.
I am looking for an algorithm which pretty much does the same as flood-fill, which is fill out a monochrome area. Instead of the recursion and the nearest-Neighbor approach i want the algorithm to be some sort of "turtle" or "mouse" that fills out the image, while leaving a path behind. This path must not contain diagonal movements. The result should be similar to a perfect Snake Game, where the entire square is filled (the snake represents the path in this case). It can cross its own path but that amount should be kept to a minimum and it should only occur in special cases (e.g: when the "mouse" enters a passage of width = 1px, where it would fill that passage out and turn around).The amount of changes in direction it takes should also be kept at a minimum.
P.S: not that this will be applied on an image, not a graph
I would model this as a graph problem where you are trying to visit all the nodes in the graph. Each pixel is a node and an edge exists between nodes that are directly next to each other.
I believe that creating an algorithm in which is a variation of a breadth first search on a graph modeled like this would achieve the result you were looking for. Ensuring that you do not visit nodes twice.
You would need to delve deeper into the implementation of the breadth first search in order to make sure it prefers a 'straight' path. Possibly when writing the breadth first search logic, create an is_straight() which checks the next node to see if it's straight or not, and prefer the straight node and only pick a non straight node when is_straight() returns false on all the child nodes.
I have a collection of lines in my diagram and I also have a point. What I want is a collection of lines which will together form a polygon through a ordered traversal. I don't need implementation or anything all I want is someone to direct me towards the algorithm I can use.
Similar problem like this have been asked but won't work for me because
One of the common asked problems is that given a polygon I need to find whether the point lies inside it or not but this won't work for me because I don't have any polygons I only have a collection of lines.
the final polygon can be convex too so simply drawing rays on every side from that point and finding intersections won't work I need something more advanced.
Sorry for all the confusion : See this for clarity https://ibb.co/nzbxGF
You need to store your collection of segments inside a suitable data structure. Namely, the chosen data structure should support the concept of faces, as you're looking for a way to find the face in which a given point resides. One such data structure is the Doubly Connected Edge List.
The Doubly Connected Edge List is a data structure that holds a subdivision of the plane. In particular, it contains a record for each face, edge, and vertex of the subdivision. It also supports walking around a face counterclockwise, which allows you to know which segments bound a particular face (such as the face containing the point you're searching for).
You can use a Sweep Line Algorithm to construct the Doubly Connected Edge List in O(nlog(n)+klog(n)) where n is the number of segments and k is the complexity of the resulting subdivision (the total number of vertices, edges, and faces). You don't have to code it from scratch as this data structure and its construction algorithm have already been implemented many times (you can use CGAL's DCEL implementation for example).
With the Doubly Connected Edge List data structure you can solve your problem by applying the approach you've suggested in your post: given an input point, solve the Point in Polygon problem for each face in the Doubly Connected Edge List and return the set of segments bounding the face you've found. However, this approach, while might be good enough for somewhat simple subdivisions, is not efficient for complex ones.
A better approach is to transform the Doubly Connected Edge List into a data structure that is specialized in point location queries: The Trapezoidal Map. This data structure can be constructed in O(nlog(n)) expected time and for any query point the expected search time is O(log(n)). As with the Doubly Connected Edge List, you don't have to implement it yourself (again, you can use CGAL's Trapezoidal Map implementation).
There are algorithms out there to find k nearest neighbors in many ways. I am eventually will have to apply these, however in my case, I can code my program to add points one-by-one rather than add all the points altogether, then run a algorithm. Is this make the problem easier, so that maybe I could use a tree, and add each node to a neighborhood tree or something. This seems like it would be faster than searching all the points linearly.
And in my program points will be moving constantly, so I will be required to update neighbors, that's why I thought it is better to use a tree or another construct to update records, rather than calculate nearest neighbors in every movement of these points. Do you know of such data structure ?
Maybe a graph datastructure/database is most appropriate due to the structural similarity.
Example: https://neo4j.com/graphgist/a7c915c8-a3d6-43b9-8127-1836fecc6e2f (I do not work for neo4j)
I am looking into a Planar Point Location, and right now thinking about make use of The Slabs approach.
I've read through a couple of articles:
Planar Point Location Using Persistent Search Trees
Persistent Data Structures
Point location on Wikipedia
I understand the concept behind a persistent balanced binary search tree, but let's omit them in this question, I don't really care about extra storage space overhead. The thing with the articles is they are discussing how speed can be improved, but don't explain basic stuff. For example:
Could you please correct me if I am wrong:
We draw a line across all intersections.
Now, we have slabs that are split by the segments at different angles.
Every intersection with any line is considered a vertex.
Slabs are sorted by order in a binary search tree (let's omit a partially persistent bst)
Somehow, sectors are sorted in those respective BST's, even though the segments dividing them are almost always at an angle. Does each node has to carry a definition of area?
Please refer to this example image:
Questions:
How would I actually figure out if the point lies in Node c and not in Node b? Is it somehow via area?
Do I instead need arrange my nodes to contain information about the segments? I could then check if the query point lies above a segment (if that's how I should determine my sectors)? If so, would I then search through a Polygon List after, to see which polygon this particular segment belongs to?
Maybe I need to store BST for each line and not a slab?
Would I then have to look at 2 BST's belonging to line on the left, and the 2nd one of the line to the right from the vertex? I could then sort the vertexes by y coordinate in each tree and return the y coordinate of a vertex (the end of a segment) right below my query point. Having done this for left and right line, I would then do a comparison to see if the names of the segment those vertexes come from actually match.
However, this will not give me the right answer, since even if the names do match, I might be below or above the segment (if I am close to it). Also, this implies I have to do 3 binary searches (1 for lines, 1 for the y-coordinate on left line, 1 for the right one), and the books says I only need to do 2 searches (1 for slab, 2nd for sector).
Could someone please point me in the direction to do it?
I probably just missed some essential thought or something.
Edit:
Here is another good article, that explains the solution to the problem, however, I don't quite understand how I would achieve the following:
"Consider any query point q ∈ R2. To find the face of G that contains q, we first use binary search with the x-coordinate of q to find the vertical slab s that contains q. Given s, we use binary search with the y-coordinate of q to find the edges of Es between which q lies. "
How exactly to find those 2 edges? Is it as simple as checking if the point lies below the segment? However, this seems like a complicated check to do (and expensive), as we descend down the tree, inspecting the other nodes.
Well, this was asked a year ago so I guess you're not going to be around to accept the answer. It's a fun question, though, so here goes anyway...
Yes, you can divide the plane into slabs using vertical lines through every intersection. The important result is that all line segments that touch a slab will go all the way through, and the order of those line segments will be the same across the entire slab.
In each slab, you make a binary search tree of those line segments, ordered by their order in the slab. The areas that you call "nodes" are the leaves of the tree, and the line segments are the internal nodes. I will call the leaves "areas" to avoid ambiguity. Since the order of the line segments is the same across the entire slab, the order in this tree is valid for every x coordinate in the slab.
to determine the area that contains any point, you find the slab that contains the point, and then do a simple search in the BST to find the area.
Lets say you're looking for point C, and you're at the node in slab 2 that contains (x2,y2) - (x3,y4). Determine whether C is above or below this line segment, and then take that branch in the tree.
For example, if C is (cx,cy) then the y coordinate of the segment at x=cx is:
testy = ((cx-x2)/(x3-x2)) * (y4-y2) + y2
If cy < testy, then take the upward branch, otherwise take the downward branch. (assuming positive Y goes downward).
When you get to a leaf, that's the area that contains C. You're done.
Now... Making a whole new tree for every slab takes a lot of space, since you can have N^2 intersection points and therefore N^2 slabs. Storing a separate tree in every slab would take O(N^3) space.
Using, say, persistent red-black trees, however, the slabs can actually share a lot of nodes. Using a simple purely functional implementation like Chris Okasaki's red-black tree takes O(log N) space per intersection for a total of O(N^2*log N) space.
I seem to remember that there is also a constant-space-per-change persistent red-black tree that would give you O(N^2), but I don't have a reference.
Note that for most real-life scenarios there are closer to O(N) intersections, because lines don't cross very much, but it's still nice to save the space by using a persistent tree.