There is list of many-to-many relations (N = 1000000). I need as fast as possible to determine index of relation in the list and enumerate all relations for a specific item.
I know that it is possible to make lookup table (with time O(1)) for from/to, but it has too big size (N*N). And I know that I can use binary search (with time O(log(N))), but it is still very slow. Are there other solutions?
C# code:
public class Relation
{
public int From;
public int To;
}
public class Table
{
public List<Relation> Relations { get; } = new List<Relation>();
public void Add(int from, int to)
{
if (IndexOf(from, to) == -1)
{
Relations.Add(new Relation() { From = from, To = to });
}
}
public int IndexOf(int from, int to)
{
// this algorithm make O(N) comparisons, but I need O(1)
for (int i = 0; i < Relations.Count; i++)
{
if (Relations[i].From == from && Relations[i].To == to) return i;
}
return -1;
}
public IEnumerable<int> FromsOf(int to)
{
// this algorithm make O(N) comparisons, but I need O(1)
for (int i = 0; i < Relations.Count; i++)
{
if (Relations[i].To == to) yield return Relations[i].From;
}
}
}
class Program
{
static void Main(string[] args)
{
Random r = new Random();
Table t = new Table();
int N = 1000000;
for (int i = 0; i < N; i++) t.Add(r.Next(N), r.Next(N));
DateTime t1 = DateTime.Now;
for (int i = 0; i < N; i++)
{
if (t.IndexOf(r.Next(N), r.Next(N)) != -1)
{
// do something
}
}
DateTime t2 = DateTime.Now;
for (int i = 0; i < N; i++)
{
foreach (int j in t.FromsOf(r.Next(N)))
{
// do something
}
}
DateTime t3 = DateTime.Now;
Console.WriteLine($"IndexOf speed = {(t2 - t1).TotalMilliseconds / N}ms");
Console.WriteLine($"FromsOf speed = {(t3 - t2).TotalMilliseconds / N}ms");
}
}
Here is the version with 2 dictionaries:
Output: