/* Sorts an array using Selection sort algorithm.
         * Prints updates if printUpdates is true.
         * Doesn't redundantly swap the last remaining element with itself.
         * Time complexity: Worst = n^2, Best = n^2, Average = n^2.
         */
        public static int[] Sort(int[] array, bool printUpdates)
        {
            ulong comparisons = 0;
            ulong swaps       = 0;
            int   n           = array.Length;

            // The leftmost element will be skipped at each successive loop, since we know it's now sorted.
            // Also, the condition is ( < n-1 ) instead of ( < n ) to avoid swapping the last element with itself.
            for (int firstUnsortedIndex = 0; firstUnsortedIndex < n - 1; firstUnsortedIndex++)
            {
                if (printUpdates)
                {
                    Console.WriteLine("Go through unsorted section to find minimum:");
                }
                // Assume the first unsorted element is the smallest, store its index
                int min        = array[firstUnsortedIndex];
                int indexOfMin = firstUnsortedIndex;
                // Iterate through the unsorted array and find the smallest element
                for (int currentIndex = firstUnsortedIndex + 1; currentIndex < n; currentIndex++)
                {
                    // Since the next line will compare elements, add 1 to comparisons
                    comparisons++;
                    if (printUpdates)
                    {
                        Console.WriteLine("^ Compare " + min.ToString().PadLeft(2) +
                                          " with " + array[currentIndex].ToString().PadLeft(2));
                    }
                    if (array[currentIndex] < min)
                    {
                        min        = array[currentIndex];
                        indexOfMin = currentIndex;
                    }
                }
                // Swap the smallest element with the first unsorted element. Count 1 more swap.
                ArrayOperations.Swap(array, indexOfMin, firstUnsortedIndex);
                swaps++;

                // Since a swap was made, print array in current state and say what was swapped
                if (printUpdates)
                {
                    Console.WriteLine("Minimum = {0}, swap with first unsorted element:", min);
                    string message = "swapped " + array[indexOfMin].ToString().PadLeft(2) +
                                     " with " + array[firstUnsortedIndex].ToString().PadLeft(2);
                    ArrayOperations.Print(array, message);
                }
            }

            // Print number of comparisons and swaps that were performed
            if (printUpdates)
            {
                Console.WriteLine("Since there's only one element left, it must be in the right place and we're done!");
                Console.WriteLine("\nNumber of comparisons: " + comparisons +
                                  "\nNumber of swaps: " + swaps);
            }

            CountAndDisplay.totalComparisonsSelection += comparisons;
            CountAndDisplay.totalSwapsSelection       += swaps;
            return(array);
        }
示例#2
0
        /* Returns the pivot for Quicksort's Partition method.
         * Choice of three methods of finding the pivot: end, random, and median-of-three
         * Choose by setting the value of 'pivotMethod' a few lines down.
         *
         * A note on median-of-three from Wikipedia:
         * "Although this approach optimizes quite well, it is typically outperformed in practice
         * by instead choosing random pivots, which has average linear time for selection and
         * average log-linear time for sorting, and avoids the overhead of computing the pivot."
         */
        public static int GetPivot(int[] array, int start, int end)
        {
            int pivotMethod = 2;    //Set here: 0 = end, 1 = random, 2 = median-of-three

            // Method 1: Pivot = end
            // This gives Quicksort a running time O(n^2) in the worst case (already sorted)
            if (pivotMethod == 0)
            {
                return(end);
            }

            // Method 2: Pivot = random
            else if (pivotMethod == 1)
            {
                // Pivot is the element at a random index in this part of the array
                Random rnd = new Random();
                int    i   = rnd.Next(start, end + 1);

                // Swap the pivot with the end (end is now pivot)
                ArrayOperations.Swap(array, i, end);
                CountAndDisplay.totalSwapsQuick++;

                return(end);
            }

            // Method 3: Pivot = 'median of three', change the array as required
            else
            {
                int mid = (start + end) / 2;

                // Ensure start < mid < end
                if (array[start] > array[end])
                {
                    ArrayOperations.Swap(array, start, end);
                    CountAndDisplay.totalSwapsQuick++;
                }
                if (array[start] > array[mid])
                {
                    ArrayOperations.Swap(array, start, mid);
                    CountAndDisplay.totalSwapsQuick++;
                }
                if (array[mid] > array[end])
                {
                    ArrayOperations.Swap(array, mid, end);
                    CountAndDisplay.totalSwapsQuick++;
                }

                // Swap mid and end (end is now pivot)
                ArrayOperations.Swap(array, end, mid);
                CountAndDisplay.totalSwapsQuick++;

                return(end);
            }
        }
示例#3
0
        /* Sets pivot to some element in the given array, and partitionIndex to the first.
         * Iterates through each element and compares against the pivot.
         * If it's less than or equal to the pivot, swap it with partitionIndex++.
         * If it's greater than pivot, leave it alone.
         * Finally, swap the pivot with the partitionIndex.
         * Now, all elements <= pivot are on its left, and elements > pivot are on the right.
         */
        public static int Partition(int[] array, int start, int end, bool printUpdates)
        {
            ulong comparisons = 0;
            ulong swaps       = 0;

            // Set pivot (one of three methods, see GetPivot method)
            int pivotIndex = GetPivot(array, start, end);
            int pivot      = array[pivotIndex];
            // Set partitionIndex to start
            int partitionIndex = start;

            if (printUpdates)
            {
                Console.WriteLine("Pivot is {0}, move < elements to left and >= to right", pivot);
            }

            // Iterate from start to end - 1 (because end is always the pivot)
            for (int i = start; i < end; i++)
            {
                // Compare each element to the pivot
                comparisons++;
                if (array[i] < pivot)
                {
                    // If it's < pivot, swap to left of partition
                    ArrayOperations.Swap(array, i, partitionIndex);
                    partitionIndex++;
                    swaps++;
                }
            }

            // Move the pivot to the partition. Now, elements left are <= pivot, right are > pivot
            ArrayOperations.Swap(array, end, partitionIndex);
            swaps++;

            CountAndDisplay.totalComparisonsQuick += comparisons;
            CountAndDisplay.totalSwapsQuick       += swaps;

            if (printUpdates)
            {
                string message = "Pivot was " + pivot.ToString().PadLeft(2) + ", moved to index " + partitionIndex.ToString().PadLeft(2);
                ArrayOperations.Print(array, message);
            }
            return(partitionIndex);
        }
        /* Sorts an array using Bubble sort algorithm.
         * Prints updates if printUpdates is true.
         * Optimised: will only loop once through an array once after it's sorted,
         * and distinguishes between 'sorted' and 'unsorted' parts.
         * Time complexity: Worst = n^2, Best = n, Average = n^2.
         */
        public static int[] Sort(int[] array, bool printUpdates)
        {
            ulong comparisons = 0;
            ulong swaps       = 0;
            // Get (length - 1) because we compare with (j + 1)
            int  n       = array.Length - 1;
            bool swapped = false;

            /* Loop through the array, checking that each element is smaller than the next.
             * If not, swap those two elements and mark 'swapped' to true.
             * Stop looping when the whole array has been checked without making a swap.
             */
            do
            {
                swapped = false;
                for (int j = 0; j < n; j++)
                {
                    // Since the next line will compare elements, add 1 to comparisons
                    comparisons++;
                    if (printUpdates)
                    {
                        Console.Write("^ Compare " + array[j].ToString().PadLeft(2) +
                                      " with " + array[j + 1].ToString().PadLeft(2));
                    }
                    if ((array[j] > array[j + 1]))
                    {
                        // Swap them, set 'swapped' to true, count 1 more swap
                        ArrayOperations.Swap(array, j, j + 1);
                        swapped = true;
                        swaps++;

                        // Since a swap was made, print array in current state and say what was swapped
                        if (printUpdates)
                        {
                            Console.WriteLine(", it's bigger so swap:");
                            string message = "swapped " + array[j + 1].ToString().PadLeft(2) +
                                             " with " + array[j].ToString().PadLeft(2);
                            ArrayOperations.Print(array, message);
                        }
                    }
                    else if (printUpdates)
                    {
                        Console.WriteLine(", it's not bigger so don't swap");
                    }
                }
                // After each loop, we know the biggest element must be sorted
                // So, it can be ignored on the next pass
                n--;
            } while (swapped);

            // Print number of comparisons and swaps that were performed
            if (printUpdates)
            {
                Console.WriteLine("Since no swaps were made this pass, we're done!");
                Console.WriteLine("\nNumber of comparisons: " + comparisons +
                                  "\nNumber of swaps: " + swaps);
            }

            CountAndDisplay.totalComparisonsBubble += comparisons;
            CountAndDisplay.totalSwapsBubble       += swaps;
            return(array);
        }