//Merges all threads together public static void MergeThreads(int[] array, int count, int[] parts, string name, Stopwatch watch) { //we always merge the sorted block at the beginning with next block //the first block is getting bigger with each cycle for (int i = 0; i < count - 1; i++) { int[] temp = new int[array.Length]; Array.Copy(array, temp, array.Length); Merge(array, temp, 0, parts[i], parts[i + 1]); //after each merge, generate a svg image showing current progress SVGgenerate.GenerateSVG(name, count, cnt++, 0, 0, array, watch.ElapsedTicks); } }
//Mergesort algorithm implementation //Sorts with the idea, that two sorted arrays can be easily merged together public void Sort(int[] array, int start, int end, bool threaded) { //create a copy of an array to measure time at first sorting int[] mergearray; if (threaded) { mergearray = array; } else { mergearray = new int[array.Length]; Array.Copy(array, mergearray, array.Length); } //a list for storing measured time List <long> time = new List <long>(); //start measuring time from the beginning of sorting var watch = new Stopwatch(); watch.Start(); time.Add(watch.ElapsedTicks); //run mergesort recursively MergeSort(mergearray, start, end, false, watch, time); watch.Stop(); if (threaded) { return; } //run a second sorting, this time the duration is already measured, so we can create frames during the run frame = 0; comparisons = 0; accesses = 0; SVGgenerate.GenerateSVG("mergesort", 0, frame, comparisons, accesses, array, time[frame]); //run mergesort recursively MergeSort(array, start, end, true, watch, time); InfoFile.CreateInfoFile("mergesort", array.Length, time.Last(), comparisons, accesses, 0); }
//auxiliary method for quicksort, finds a pivot public int FindPivot(int[] array, int left, int right, List <long> time, Stopwatch watch, bool draw) { access++; //begin at the first element of parted array int pivot = array[left]; //until a pivot is found and a value is returned, repeat while (true) { comparison = comparison + 3; access = access + 2; while (array[left] < pivot) { left++; } while (array[right] > pivot) { right--; } //if left is smaller than right, swap them if (left < right) { int temp = array[left]; array[left] = array[right]; array[right] = temp; //decide whether to save time into a list of times in case of first run or draw an image in case of second run if (draw) { frame++; SVGgenerate.GenerateSVG("quicksort", 0, frame, comparison, access, array, time[frame]); } else { time.Add(watch.ElapsedTicks); } } //if swapping isn't needed, pivot is found, return a value else { return(right); } } }
//recursively splits an array into two parts and merges two sorted parts public static void MergeSort(int[] array, int start, int end, bool draw, Stopwatch watch, List <long> time) { if (start < end) { int mid = (start + end) / 2; MergeSort(array, start, mid, draw, watch, time); MergeSort(array, mid + 1, end, draw, watch, time); Merge(array, start, mid, end); if (draw) { frame++; SVGgenerate.GenerateSVG("mergesort", 0, frame, comparisons, accesses, array, time[frame]); } else { time.Add(watch.ElapsedTicks); } } }
//Bucketsort algorithm implementation //It doesn't use any comparing, this algorithm sorts an array by putting numbers in buckets according to the decimal value public void Sort(int[] array, int start, int end, bool threaded) { int buckets = array.Length; //in case of two steps sorting for singlethreaded run, we copy the contents of an array to an auxiliary one int[] bucketarray; if (threaded) { bucketarray = array; } else { bucketarray = new int[array.Length]; Array.Copy(array, bucketarray, array.Length); } //a list for storing measured time List <long> time = new List <long>(); int frame = 0; int comparisons = 0; int accesses = 0; //start measuring time from the beginning of sorting var watch = new Stopwatch(); watch.Start(); time.Add(watch.ElapsedTicks); //ten buckets for numbers 0..9 Queue <int>[] sub = new Queue <int> [10]; //initialize queues for (int i = 0; i < 10; i++) { sub[i] = new Queue <int>(); } int k, l, m; //for each decimal of maximum number in the array for (int j = 10; j <= (buckets * 10); j = (j * 10)) { k = start; //put every number in according bucket while (k <= end) { l = (bucketarray[k]) % j; m = l % (j / 10); l = (l - m) / (j / 10); sub[l].Enqueue(bucketarray[k]); k++; } //starting index of an array k = start; //go through all ten buckets for (int i = 0; i < 10; i++) { //until the current buckets isn't empty, pop an element and put it into an array while (sub[i].Count != 0) { bucketarray[k] = sub[i].Dequeue(); //increment the counter k++; time.Add(watch.ElapsedTicks); } } } //in case of multithreaded sorting, we sorted required part of an array and can exit if (threaded) { return; } watch.Stop(); //run a second sorting, this time the duration is already measured, so we can create frames during the run SVGgenerate.GenerateSVG("bucketsort", 0, frame, comparisons, accesses, array, time[frame]); //ten buckets for numbers 0..9 Queue <int>[] secsub = new Queue <int> [10]; //initialize queues for (int i = 0; i < 10; i++) { accesses++; secsub[i] = new Queue <int>(); } //for each decimal of maximum number in the array for (int j = 10; j <= (buckets * 10); j = (j * 10)) { k = 0; //put every number in according bucket while (k < array.Length) { accesses++; l = (array[k]) % j; m = l % (j / 10); l = (l - m) / (j / 10); accesses++; secsub[l].Enqueue(array[k]); k++; } //starting index of an array k = 0; //go through all ten buckets for (int i = 0; i < 10; i++) { //until the current buckets isn't empty, pop an element and put it into an array while (secsub[i].Count != 0) { accesses++; array[k] = secsub[i].Dequeue(); //increment the counter k++; frame++; SVGgenerate.GenerateSVG("bucketsort", 0, frame, comparisons, accesses, array, time[frame]); } } } //before we exit, we create an info file summarizing the result of an algorithm InfoFile.CreateInfoFile("bucketsort", array.Length, time.Last(), comparisons, accesses, 0); }
//Shakersort algorithm implementation //Also sometimes named cocktailsort, it is advanced bubblesort, that returns when it reaches an end of the array. public void Sort(int[] array, int start, int end, bool threaded) { //in case of two steps sorting for singlethreaded run, we copy the contents of an array to an auxiliary one int[] shakerarray; if (threaded) { shakerarray = array; } else { shakerarray = new int[array.Length]; Array.Copy(array, shakerarray, array.Length); } //a list for storing measured time List <long> time = new List <long>(); //start measuring time from the beginning of sorting var watch = new Stopwatch(); watch.Start(); time.Add(watch.ElapsedTicks); //go through the current array for (int i = start; i < end; i++) { //indicator showing if the elements were swapped bool swap = false; //go from current element to the end of an array for (int j = i; j < end; j++) { //if the left element is bigger than the right, swap them if (shakerarray[j + 1] < shakerarray[j]) { int temp = shakerarray[j + 1]; shakerarray[j + 1] = shakerarray[j]; shakerarray[j] = temp; time.Add(watch.ElapsedTicks); //mark that some elements were swapped swap = true; } } //return back, so go from the end of an array to current element, for (int j = end; j > start; j--) { //if the right element is smaller than the left, swap them if (shakerarray[j] < shakerarray[j - 1]) { int temp = shakerarray[j - 1]; shakerarray[j - 1] = shakerarray[j]; shakerarray[j] = temp; time.Add(watch.ElapsedTicks); //mark that some elements were swapped swap = true; } } //if no elements were swapped, that means the array is sorted if (swap == false) { break; } } watch.Stop(); //in case of multithreaded sorting, we sorted required part of an array and can exit if (threaded) { return; } //run a second sorting, this time the duration is already measured, so we can create frames during the run int frame = 0; int comparison = 0; int access = 0; SVGgenerate.GenerateSVG("shakersort", 0, frame, comparison, access, array, time[frame]); //go through the current array for (int i = 0; i < array.Length / 2; i++) { //indicator showing if the elements were swapped bool swap = false; //go from current element to the end of an array for (int j = i; j < array.Length - i - 1; j++) { comparison++; access = access + 2; //if the left element is bigger than the right, swap them if (array[j + 1] < array[j]) { int temp = array[j + 1]; array[j + 1] = array[j]; array[j] = temp; frame++; SVGgenerate.GenerateSVG("shakersort", 0, frame, comparison, access, array, time[frame]); //mark that some lements were swapped swap = true; } } //return back, so go from the end of an array to current element for (int j = array.Length - 2 - i; j > i; j--) { comparison++; access = access + 2; //if the right element is smaller than the left, swap them if (array[j] < array[j - 1]) { int temp = array[j - 1]; array[j - 1] = array[j]; array[j] = temp; frame++; SVGgenerate.GenerateSVG("shakersort", 0, frame, comparison, access, array, time[frame]); //mark that some lements were swapped swap = true; } } //if no elements were swapped, that means the array is sorted if (swap == false) { break; } } //before we exit, we create an info file summarizing the result of an algorithm InfoFile.CreateInfoFile("shakersort", array.Length, time.Last(), comparison, access, 0); }
//method used to run sorting on n separate threads //we get a number of threads to sort on, unsorted array, and an object containing an algorithm to sort with public static void RunThreads(int threadCount, int[] array, SortingAlgorithm Sorting) { cnt = 0; //get name of sorting algorithm from name of it's class string name = Sorting.GetType().Name; //generate first frame of unsorted array SVGgenerate.GenerateSVG(name, threadCount, cnt++, 0, 0, array, 0); //size of an subarray, which will be sorted by one thread int part = array.Length / threadCount; //an array containing borders of each part int[] parts = new int[threadCount]; //array containing all threads we are sorting with Thread[] objThread = new Thread[threadCount]; //Stopwatch for measuring sorting time var watch = new Stopwatch(); watch.Start(); //we create a thread for each part and add that thread to an array of threads for (int i = 0; i < threadCount - 1; i++) { //we save the iterator to new integer, else it's value would be non-deterministic in multithreading int c = i; Thread ThreadSorting = new Thread(() => Sorting.Sort(array, c * part, (c + 1) * part - 1, true)); objThread[c] = ThreadSorting; parts[i] = (c + 1) * part - 1; } //we create last part, which is supposed to be bigger and contain last elements Thread LastThread = new Thread(() => Sorting.Sort(array, (threadCount - 1) * part, array.Length - 1, true)); objThread[threadCount - 1] = LastThread; parts[threadCount - 1] = array.Length - 1; //starting of all threads foreach (var thread in objThread) { thread.Start(); } //waiting for all threads to finish foreach (var thread in objThread) { thread.Join(); } //generate a picture of an array after it is sorted by threads //due to the non-deterministic nature of threads, we are not able to generate it sooner //however, the user can use sorting without multithreading to see the progress of each algorithm SVGgenerate.GenerateSVG(name, threadCount, cnt++, 0, 0, array, watch.ElapsedTicks); //Merge all threads together MergeThreads(array, threadCount, parts, name, watch); watch.Stop(); //create an info file about this sorting InfoFile.CreateInfoFile(name, array.Length, watch.ElapsedTicks, 0, 0, threadCount); }
//Quicksort algorithm implemetation //Divide and counter algorithm, it picks a pivot and partitions an array around the pivot. //This implementation is iterative, not recursive. public void Sort(int[] array, int start, int end, bool threaded) { int left, right; //stack for storing values indicating an array partition Stack <int> stack = new Stack <int>(); stack.Push(start); stack.Push(end); //in case of two steps sorting for singlethreaded run, we copy the contents of an array to an auxiliary one int[] quickarray; if (threaded) { quickarray = array; } else { quickarray = new int[array.Length]; Array.Copy(array, quickarray, array.Length); } //a list for storing measured time List <long> time = new List <long>(); //start measuring time from the beginning of sorting var watch = new Stopwatch(); watch.Start(); //iterate until the stack is empty, which means that the array is sorted while (stack.Count != 0) { time.Add(watch.ElapsedTicks); //pop two values of stack, bounding the current part of an array right = stack.Pop(); left = stack.Pop(); //selects a pivot int pivot = FindPivot(quickarray, left, right, time, watch, false); //push a correct new boundaries of new partitions into the stack if (pivot - 1 > left) { stack.Push(left); stack.Push(pivot - 1); } if (pivot + 1 < right) { stack.Push(pivot + 1); stack.Push(right); } } watch.Stop(); //in case of multithreaded sorting, we sorted required part of an array and can exit if (threaded) { return; } //run a second sorting, this time the duration is already measured, so we can create frames during the run frame = 0; access = 0; comparison = 0; stack.Clear(); stack.Push(0); stack.Push(array.Length - 1); SVGgenerate.GenerateSVG("quicksort", 0, frame, comparison, access, array, 0); while (stack.Count != 0) { //pop two values of stack, bounding the current part of an array right = stack.Pop(); left = stack.Pop(); //selects a pivot int pivot = FindPivot(array, left, right, time, watch, true); //push a correct new boundaries of new partitions into the stack comparison++; if (pivot - 1 > left) { stack.Push(left); stack.Push(pivot - 1); } comparison++; if (pivot + 1 < right) { stack.Push(pivot + 1); stack.Push(right); } } //before we exit, we create an info file summarizing the result of an algorithm InfoFile.CreateInfoFile("quicksort", array.Length, time.Last(), comparison, access, 0); }
//Bubblesort algorithm implementation. //It is the simplest algorithm, it works by repeatedly swapping adjanced elements, that are in the wrong order. public void Sort(int[] array, int start, int end, bool threaded) { //in case of two steps sorting for singlethreaded run, we copy the contents of an array to an auxiliary one int[] bubblearray; if (threaded) { bubblearray = array; } else { bubblearray = new int[array.Length]; Array.Copy(array, bubblearray, array.Length); } //a list for storing measured time List <long> time = new List <long>(); //start measuring time from the beginning of sorting var watch = new Stopwatch(); watch.Start(); time.Add(watch.ElapsedTicks); //go through the whole array for (int i = start; i <= end; i++) { //start at beginning and continue to the current element of an array for (int j = start; j <= end - 1; j++) { //if the left element is bigger than the right, swap them if (bubblearray[j + 1] < bubblearray[j]) { //create a temporary integer to store a value in int temp = bubblearray[j + 1]; bubblearray[j + 1] = bubblearray[j]; bubblearray[j] = temp; time.Add(watch.ElapsedTicks); } } } watch.Stop(); //in case of multithreaded sorting, we sorted required part of an array and can exit if (threaded) { return; } //run a second sorting, this time the duration is already measured, so we can create frames during the run int frame = 0; int comparisons = 0; int accesses = 0; SVGgenerate.GenerateSVG("bubblesort", 0, frame, comparisons, accesses, array, time[frame]); for (int i = 0; i < array.Length - 1; i++) { //start at beginning and continue to the current element of an array for (int j = 0; j < array.Length - i - 1; j++) { comparisons++; accesses = accesses + 2; //if the left element is bigger than the right, swap them if (array[j + 1] < array[j]) { //create a temporary integer to store a value in int temp = array[j + 1]; array[j + 1] = array[j]; array[j] = temp; frame++; SVGgenerate.GenerateSVG("bubblesort", 0, frame, comparisons, accesses, array, time[frame]); } } } //before we exit, we create an info file summarizing the result of an algorithm InfoFile.CreateInfoFile("bubblesort", array.Length, time.Last(), comparisons, accesses, 0); }
//Selectionsort algorithm implementation //It sorts an array by repeatedly finding a maximal element and putting it at the end of the array. public void Sort(int[] array, int start, int end, bool threaded) { //in case of two steps sorting for singlethreaded run, we copy the contents of an array to an auxiliary one int[] selectionarray; if (threaded) { selectionarray = array; } else { selectionarray = new int[array.Length]; Array.Copy(array, selectionarray, array.Length); } //a list for storing measured time List <long> time = new List <long>(); //start measuring time from the beginning of sorting var watch = new Stopwatch(); watch.Start(); time.Add(watch.ElapsedTicks); //go through the current array for (int i = start; i <= end; i++) { //mark a maximal value int max = i; //go through an array from a current element to the end of an array for (int j = i + 1; j <= end; j++) { //if a current element is bigger than marked maximum if (selectionarray[j] < selectionarray[max]) { max = j; } } //swap the last element with a maximum element int temp = selectionarray[i]; selectionarray[i] = selectionarray[max]; selectionarray[max] = temp; time.Add(watch.ElapsedTicks); } watch.Stop(); //in case of multithreaded sorting, we sorted required part of an array and can exit if (threaded) { return; } //run a second sorting, this time the duration is already measured, so we can create frames during the run int frame = 0; int comparison = 0; int access = 0; SVGgenerate.GenerateSVG("selectionsort", 0, frame, comparison, access, array, time[frame]); //go through the current array for (int i = 0; i < array.Length - 1; i++) { //mark a maximal value int max = i; //go through an array from a current element to the end of an array for (int j = i + 1; j < array.Length; j++) { comparison++; access = access + 2; //if a current element is bigger than marked maximum if (array[j] < array[max]) { max = j; } } access = access + 2; //swap the last element with a maximum element int temp = array[i]; array[i] = array[max]; array[max] = temp; frame++; SVGgenerate.GenerateSVG("selectionsort", 0, frame, comparison, access, array, time[frame]); } //before we exit, we create an info file summarizing the result of an algorithm InfoFile.CreateInfoFile("selectionsort", array.Length, time.Last(), comparison, access, 0); }
//Insertionsort algorithm implementation //Iterates through the array and when it encounters an element, puts it where it belongs in a sorted array. public void Sort(int[] array, int start, int end, bool threaded) { //in case of two steps sorting for singlethreaded run, we copy the contents of an array to an auxiliary one int[] insertarray; if (threaded) { insertarray = array; } else { insertarray = new int[array.Length]; Array.Copy(array, insertarray, array.Length); } //a list for storing measured time List <long> time = new List <long>(); //start measuring time from the beginning of sorting var watch = new Stopwatch(); watch.Start(); time.Add(watch.ElapsedTicks); //iterate through the current array for (int i = start; i < end; i++) { //get a current element int j = i + 1; int temp = insertarray[j]; //iterate through a sorted array to a place where the current element belongs while (j > start && temp < insertarray[j - 1]) { //swap the elements to preserve a sorted array insertarray[j] = insertarray[j - 1]; j--; insertarray[j] = temp; time.Add(watch.ElapsedTicks); } } watch.Stop(); //in case of multithreaded sorting, we sorted required part of an array and can exit if (threaded) { return; } //run a second sorting, this time the duration is already measured, so we can create frames during the run int frame = 0; int comparisons = 0; int accesses = 0; for (int i = 0; i < array.Length - 1; i++) { //get a current element int j = i + 1; int temp = array[j]; accesses++; //iterate through a sorted array to a place where the current element belongs while (j > 0 && temp < array[j - 1]) { comparisons = comparisons + 2; accesses = accesses + 2; //swap the elements to preserve a sorted array array[j] = array[j - 1]; j--; array[j] = temp; frame++; SVGgenerate.GenerateSVG("insertsort", 0, frame, comparisons, accesses, array, time[frame]); } } //before we exit, we create an info file summarizing the result of an algorithm InfoFile.CreateInfoFile("insertionsort", array.Length, time.Last(), comparisons, accesses, 0); }