Skip to content

Commit

Permalink
Adding some more algorithms and utilities to algs4:
Browse files Browse the repository at this point in the history
- CC
- ClosestPair
- CollisionSystem
- Cycle
- Date
- DegreesOfSeparation
- DepthFirstDirectedPaths
- DepthFirstPaths
- LSD
- MSD
  • Loading branch information
mina-asham committed May 10, 2015
1 parent a3ffc22 commit abe80ff
Show file tree
Hide file tree
Showing 11 changed files with 1,817 additions and 0 deletions.
10 changes: 10 additions & 0 deletions algs4/algs4.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,18 @@
<Compile Include="algs4\BST.cs" />
<Compile Include="algs4\BTree.cs" />
<Compile Include="algs4\Cat.cs" />
<Compile Include="algs4\CC.cs" />
<Compile Include="algs4\ClosestPair.cs" />
<Compile Include="algs4\CollisionSystem.cs" />
<Compile Include="algs4\Complex.cs" />
<Compile Include="algs4\Count.cs" />
<Compile Include="algs4\Counter.cs" />
<Compile Include="algs4\CPM.cs" />
<Compile Include="algs4\Cycle.cs" />
<Compile Include="algs4\Date.cs" />
<Compile Include="algs4\DeDup.cs" />
<Compile Include="algs4\DegreesOfSeparation.cs" />
<Compile Include="algs4\DepthFirstDirectedPaths.cs" />
<Compile Include="algs4\DepthFirstOrder.cs" />
<Compile Include="algs4\DepthFirstSearch.cs" />
<Compile Include="algs4\Digraph.cs" />
Expand Down Expand Up @@ -97,9 +104,11 @@
<Compile Include="algs4\KWIK.cs" />
<Compile Include="algs4\LongestCommonSubstring.cs" />
<Compile Include="algs4\LookupIndex.cs" />
<Compile Include="algs4\LSD.cs" />
<Compile Include="algs4\LZW.cs" />
<Compile Include="algs4\MergeBU.cs" />
<Compile Include="algs4\MinPQ.cs" />
<Compile Include="algs4\MSD.cs" />
<Compile Include="algs4\Multiway.cs" />
<Compile Include="algs4\NFA.cs" />
<Compile Include="algs4\Particle.cs" />
Expand Down Expand Up @@ -129,6 +138,7 @@
<Compile Include="algs4\Genome.cs" />
<Compile Include="algs4\LookupCSV.cs" />
<Compile Include="algs4\LRS.cs" />
<Compile Include="algs4\DepthFirstPaths.cs" />
<Compile Include="stdlib\Picture.cs" />
<Compile Include="stdlib\StdDraw.cs" />
<Compile Include="algs4\Stopwatch.cs" />
Expand Down
154 changes: 154 additions & 0 deletions algs4/algs4/CC.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
using System;
using algs4.stdlib;

namespace algs4.algs4
{
public class CC
{
/// <summary>
/// marked[v] = has vertex v been marked?
/// </summary>
private readonly bool[] _marked;

/// <summary>
/// id[v] = id of connected component containing v
/// </summary>
private readonly int[] _id;

/// <summary>
/// size[id] = number of vertices in given component
/// </summary>
private readonly int[] _size;

/// <summary>
/// Number of connected components
/// </summary>
private readonly int _count;

/// <summary>
/// Computes the connected components of the undirected graph G.
/// </summary>
/// <param name="g">the graph</param>
public CC(Graph g)
{
_marked = new bool[g.V()];
_id = new int[g.V()];
_size = new int[g.V()];
for (int v = 0; v < g.V(); v++)
{
if (!_marked[v])
{
DFS(g, v);
_count++;
}
}
}

/// <summary>
/// Depth-first search
/// </summary>
/// <param name="g"></param>
/// <param name="v"></param>
private void DFS(Graph g, int v)
{
_marked[v] = true;
_id[v] = _count;
_size[_count]++;
foreach (int w in g.Adj(v))
{
if (!_marked[w])
{
DFS(g, w);
}
}
}

/// <summary>
/// Returns the component id of the connected component containing vertex v.
/// </summary>
/// <param name="v">the vertex</param>
/// <returns>the component id of the connected component containing vertex v</returns>
public int Id(int v)
{
return _id[v];
}

/// <summary>
/// Returns the number of vertices in the connected component containing vertex v.
/// </summary>
/// <param name="v">the vertex</param>
/// <returns>the number of vertices in the connected component containing vertex v</returns>
public int Size(int v)
{
return _size[_id[v]];
}

/// <summary>
/// Returns the number of connected components.
/// </summary>
/// <returns>the number of connected components</returns>
public int Count()
{
return _count;
}

/// <summary>
/// Are vertices v and w in the same connected component?
/// </summary>
/// <param name="v">one vertex</param>
/// <param name="w">the other vertex</param>
/// <returns>true if vertices v and w are in the same connected component, and false otherwise</returns>
public bool Connected(int v, int w)
{
return Id(v) == Id(w);
}

/// <summary>
/// Are vertices v and w in the same connected component?
/// </summary>
/// <param name="v">one vertex</param>
/// <param name="w">the other vertex</param>
/// <returns>true if vertices v and w are in the same connected component, and false otherwise</returns>
[Obsolete("Use connected(v, w) instead.")]
public bool AreConnected(int v, int w)
{
return Id(v) == Id(w);
}

/// <summary>
/// Unit tests the CC data type.
/// </summary>
/// <param name="args"></param>
public static void RunMain(string[] args)
{
In input = new In(args[0]);
Graph g = new Graph(input);
CC cc = new CC(g);

// number of connected components
int m = cc.Count();
StdOut.PrintLn(m + " components");

// compute list of vertices in each connected component
Queue<int>[] components = new Queue<int>[m];
for (int i = 0; i < m; i++)
{
components[i] = new Queue<int>();
}
for (int v = 0; v < g.V(); v++)
{
components[cc.Id(v)].Enqueue(v);
}

// print results
for (int i = 0; i < m; i++)
{
foreach (int v in components[i])
{
StdOut.Print(v + " ");
}
StdOut.PrintLn();
}
}
}
}
200 changes: 200 additions & 0 deletions algs4/algs4/ClosestPair.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
using System;
using algs4.stdlib;

namespace algs4.algs4
{
public class ClosestPair
{
/// <summary>
/// Closest pair of points and their Euclidean distance
/// </summary>
private Point2D _best1, _best2;

private double _bestDistance = double.PositiveInfinity;

public ClosestPair(Point2D[] points)
{
int n = points.Length;
if (n <= 1)
{
return;
}

// sort by x-coordinate (breaking ties by y-coordinate)
Point2D[] pointsByX = new Point2D[n];
for (int i = 0; i < n; i++)
{
pointsByX[i] = points[i];
}
Array.Sort(pointsByX, Point2D.XOrderComparer);

// check for coincident points
for (int i = 0; i < n - 1; i++)
{
if (pointsByX[i].Equals(pointsByX[i + 1]))
{
_bestDistance = 0.0;
_best1 = pointsByX[i];
_best2 = pointsByX[i + 1];
return;
}
}

// sort by y-coordinate (but not yet sorted)
Point2D[] pointsByY = new Point2D[n];
for (int i = 0; i < n; i++)
{
pointsByY[i] = pointsByX[i];
}

// auxiliary array
Point2D[] aux = new Point2D[n];

Closest(pointsByX, pointsByY, aux, 0, n - 1);
}

/// <summary>
/// Find closest pair of points in pointsByX[lo..hi]
/// precondition: pointsByX[lo..hi] and pointsByY[lo..hi] are the same sequence of points
/// precondition: pointsByX[lo..hi] sorted by x-coordinate
/// postcondition: pointsByY[lo..hi] sorted by y-coordinate
/// </summary>
/// <param name="pointsByX"></param>
/// <param name="pointsByY"></param>
/// <param name="aux"></param>
/// <param name="lo"></param>
/// <param name="hi"></param>
/// <returns></returns>
private double Closest(Point2D[] pointsByX, Point2D[] pointsByY, Point2D[] aux, int lo, int hi)
{
if (hi <= lo)
{
return double.PositiveInfinity;
}

int mid = lo + (hi - lo) / 2;
Point2D median = pointsByX[mid];

// compute closest pair with both endpoints in left subarray or both in right subarray
double delta1 = Closest(pointsByX, pointsByY, aux, lo, mid);
double delta2 = Closest(pointsByX, pointsByY, aux, mid + 1, hi);
double delta = Math.Min(delta1, delta2);

// merge back so that pointsByY[lo..hi] are sorted by y-coordinate
Merge(pointsByY, aux, lo, mid, hi);

// aux[0..M-1] = sequence of points closer than delta, sorted by y-coordinate
int m = 0;
for (int i = lo; i <= hi; i++)
{
if (Math.Abs(pointsByY[i].X() - median.X()) < delta)
{
aux[m++] = pointsByY[i];
}
}

// compare each point to its neighbors with y-coordinate closer than delta
for (int i = 0; i < m; i++)
{
// a geometric packing argument shows that this loop iterates at most 7 times
for (int j = i + 1; (j < m) && (aux[j].Y() - aux[i].Y() < delta); j++)
{
double distance = aux[i].DistanceTo(aux[j]);
if (distance < delta)
{
delta = distance;
if (distance < _bestDistance)
{
_bestDistance = delta;
_best1 = aux[i];
_best2 = aux[j];
}
}
}
}
return delta;
}

public Point2D Either()
{
return _best1;
}

public Point2D Other()
{
return _best2;
}

public double Distance()
{
return _bestDistance;
}

/// <summary>
/// Is v &lt; w ?
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="v"></param>
/// <param name="w"></param>
/// <returns></returns>
private static bool Less<T>(T v, T w) where T : IComparable<T>
{
return (v.CompareTo(w) < 0);
}

/// <summary>
/// Stably merge a[lo .. mid] with a[mid+1 ..hi] using aux[lo .. hi]
/// precondition: a[lo .. mid] and a[mid+1 .. hi] are sorted subarrays
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="a"></param>
/// <param name="aux"></param>
/// <param name="lo"></param>
/// <param name="mid"></param>
/// <param name="hi"></param>
private static void Merge<T>(T[] a, T[] aux, int lo, int mid, int hi) where T : IComparable<T>
{
// copy to aux[]
for (int k = lo; k <= hi; k++)
{
aux[k] = a[k];
}

// merge back to a[]
int i = lo, j = mid + 1;
for (int k = lo; k <= hi; k++)
{
if (i > mid)
{
a[k] = aux[j++];
}
else if (j > hi)
{
a[k] = aux[i++];
}
else if (Less(aux[j], aux[i]))
{
a[k] = aux[j++];
}
else
{
a[k] = aux[i++];
}
}
}

public static void RunMain(string[] args)
{
int n = StdIn.ReadInt();
Point2D[] points = new Point2D[n];
for (int i = 0; i < n; i++)
{
double x = StdIn.ReadDouble();
double y = StdIn.ReadDouble();
points[i] = new Point2D(x, y);
}
ClosestPair closest = new ClosestPair(points);
StdOut.PrintLn(closest.Distance() + " from " + closest.Either() + " to " + closest.Other());
}
}
}
Loading

0 comments on commit abe80ff

Please sign in to comment.