//Time: O(|v|^2) //Space: O(V) //The main function for doing dijkstra's algorithm and resurning the results. public List <double> dijkstras() { //Console.WriteLine("Inside array dijkstras"); int max = Int32.MaxValue; //We start by adding all values to infinity for (int i = 0; i < points.Count; i++) { //Insert //Time: O(1) Beacuse your doing it for one point. //Space: O(1) Beacuse your making the queue. distance.Add(max); previous.Add(max); queue.Add(max); } distance[startIndex] = 0; queue[startIndex] = 0; int minIndex = startIndex; //to compare and change indexes int minusOnes = 0; EuclideanDistanceImplementation edi = new EuclideanDistanceImplementation(); while (minusOnes < queue.Count) { double minValue = max; //Console.WriteLine("minusOnes " + minusOnes); //the deleteMin function //Time: O(|v|) Because you have to iterate over every point to find the minimum. //Space: O(1) Nothing changed. for (int i = 0; i < queue.Count; i++) { //Console.WriteLine("Dist is " + queue[i]); if (queue[i] != -1 && queue[i] < minValue) { minIndex = i; minValue = queue[i]; //Console.WriteLine("min index is " + i + " of " + queue[i]); } } //Console.WriteLine("The current min Index is " + minIndex); //previous.Add(points[minIndex]); queue[minIndex] = -1;//set the value to -1 to take it out, basically //update the distances of each of this node's directed edges. O(3) for (int i = 0; i < adjacencyList[minIndex].Count; i++) { int currAdj = adjacencyList[minIndex].ElementAt(i); //Console.WriteLine("currAdj is " + currAdj + " of " + adjacencyList[minIndex]); double dist = edi.calculate(points[minIndex], points[currAdj]); //Console.WriteLine("dist path of " + currAdj +" is " + distance[currAdj] + " versus " + (distance[minIndex] + dist)); if (distance[currAdj] > distance[minIndex] + dist) { distance[currAdj] = distance[minIndex] + dist; //Console.WriteLine("Add " + currAdj + " from point " + minIndex); //previous.Add(minIndex); previous[currAdj] = minIndex; //decreaseKey //Time: O(1) Because you can directly access the index. //Space: O(1) Because you change only one thing. queue[currAdj] = distance[currAdj]; } } minusOnes++; } previous.Add(endIndex); return(previous); }
private void solveButton_Clicked() { // *** Implement this method, use the variables "startNodeIndex" and "stopNodeIndex" as the indices for your start and stop points, respectively *** //Here we define the data objects we'll be using String s = sourceNodeBox.Text; int startIndex = Int32.Parse(s); s = targetNodeBox.Text; int endIndex = Int32.Parse(s); EuclideanDistanceImplementation edi = new EuclideanDistanceImplementation(); Font arialFont = new Font("Arial", 11); Pen p = new Pen(Color.Black, 1); double totalDistance = 0; DateTime startTime; double arrayTime = 0; double heapTime = 0; double elapsedMillisecondsTime = 0; if (arrayCheckBox.Checked == true) { //start the timer startTime = DateTime.Now; //compute dijkstra's algorithm with the data we have. ArrayImplementation ai = new ArrayImplementation(startIndex, endIndex, points, adjacencyList); List <double> previous = ai.dijkstras();//returns previous with all the indexes till the endIndex. int currIndex = endIndex; //Draw the shortest path with the costs backwards //Time: O(|v|) Because you may have to draw each point at worst. //Space: O(1) Beacuse you only change one point. while (currIndex != startIndex) { //Console.WriteLine("Here"); //Console.WriteLine("Prev " + previous.ElementAt(currIndex)); //make sure that we can actually reach this thing if (previous.ElementAt(currIndex) == 2147483647) { this.pathCostBox.Text = "unreachable"; return; } //draw the line graphics.DrawLine(p, points[currIndex], points[(int)previous.ElementAt(currIndex)]); //get and display length for every line drawn double dist = edi.calculate(points[currIndex], points[(int)previous.ElementAt(currIndex)]); totalDistance = totalDistance + dist; string str = Convert.ToString((int)dist); //calculation for the slope of the line and put it in the middle RectangleF rectf = new RectangleF(70, 90, 80, 80);//x, y, width, height rectf.X = Math.Abs(points[(int)previous.ElementAt(currIndex)].X + points[currIndex].X) / 2; rectf.Y = Math.Abs(points[(int)previous.ElementAt(currIndex)].Y + points[currIndex].Y) / 2; graphics.DrawString(str, arialFont, Brushes.Black, rectf); currIndex = (int)previous.ElementAt(currIndex); //Stop the timer and write the values to the forms this.pathCostBox.Text = Convert.ToString(totalDistance); elapsedMillisecondsTime = (DateTime.Now - startTime).TotalMilliseconds; arrayTime = elapsedMillisecondsTime / 10000; this.arrayTimeBox.Text = Convert.ToString(arrayTime); } } //Now do the same thing with a Heap //O(log |v|)) //start the timer startTime = DateTime.Now; HeapImplementation heapQueue = new HeapImplementation(points.Count); //ArrayQueue List <double> dist1 = new List <double>(); List <int> prev1 = new List <int>(); List <double> dist2 = new List <double>(); List <int> prev2 = new List <int>(); totalDistance = 0; for (int u = 0; u < points.Count; u++) { dist1.Add(Int16.MaxValue); prev1.Add(-1); dist2.Add(Int16.MaxValue); prev2.Add(-1); } dist1[startNodeIndex] = 0; dist2[startNodeIndex] = 0; //Heap implementation for (int u = 0; u < dist2.Count; u++) { Node node = new Node(u); heapQueue.Add(node, dist2[u]); } while (heapQueue.count > 0) { Node min = heapQueue.ExtractMin(); foreach (int adj in adjacencyList[min.pointsIndex]) { double newDistance = dist2[min.pointsIndex] + edi.getMagnitude(min, adj, points); if (dist2[adj] > newDistance) { dist2[adj] = newDistance; prev2[adj] = min.pointsIndex; heapQueue.DecreasePriority(adj, newDistance); } } } //Draw the shortest path with the costs backwards //Time: O(|v|) Because you may have to draw each point at worst. //Space: O(1) Beacuse you only change one point. int currIndexToDraw = stopNodeIndex; while (currIndexToDraw != startNodeIndex) { int prevIndex = prev2[currIndexToDraw]; //Console.WriteLine("Here"); //Console.WriteLine("Prev " + points[currIndexToDraw]); //make sure that we can actually reach this thing if (prevIndex > points.Count - 1 || prevIndex < 0) { this.pathCostBox.Text = "unreachable"; return; } graphics.DrawLine(p, points[currIndexToDraw], points[prevIndex]); double currDistance = edi.calculate(points[prevIndex], points[currIndexToDraw]); totalDistance += currDistance; String text = Convert.ToString((int)currDistance); RectangleF drawingBox = new RectangleF(Math.Abs(points[prevIndex].X + points[currIndexToDraw].X) / 2, Math.Abs(points[prevIndex].Y + points[currIndexToDraw].Y) / 2, 80, 80); graphics.DrawString(text, new Font("Arial", 11), Brushes.Black, drawingBox); currIndexToDraw = prev2[currIndexToDraw]; } this.pathCostBox.Text = Convert.ToString(totalDistance); //Now set the time it takes for all this to happen elapsedMillisecondsTime = (DateTime.Now - startTime).TotalMilliseconds; heapTime = elapsedMillisecondsTime / 10000; this.heapTimeBox.Text = Convert.ToString(heapTime); if (arrayCheckBox.Checked == true) { this.differenceBox.Text = Convert.ToString(arrayTime / heapTime); } }