Quick Sort on C# using only while loop - c#

I've been trying to implement quick sort in a particular way and I couldn't find it all over the internet-
I'm choosing randomly a pivot (I decided it's going to be the last
the item on the right side)
i index is the start index
j index is end-2 (to skip pivot)
when one item is bigger on the left and another item is smaller on the right, I'm swapping between them
after i is meeting j, I can tell for certain that all the items from 0 to i are smaller than the pivot and all the items from j to the end of the array are bigger than the pivot
now, I want to put the pivot in the correct place - it should be between i to j, and return its index
The problem is that I have a mistake in my algorithm and I can't figure it out. Can anyone tell me what am I doing wrong?
Here is my code:
public static void swap(int[] a, int i, int j)
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
public static int partition(int[] a, int start, int end)
{
int pivot = a[end];
int i = start;
int j = end - 1;
while (i < j)
{
while (i < j && a[i] <= pivot)
i++;
while (i < j && a[j] > pivot)
j--;
swap(a, i, j);
}
swap(a, i+1, end);
return i+1 ;
}
public static void QuickSort(int[] a, int start, int end)
{
if (start >= end)
return;
int p = partition(a, start, end);
QuickSort(a, start, p - 1);
QuickSort(a, p + 1, end);
}
static void Main(string[] args)
{
int[] a = { 9, 1, 4, 7, 3 };
QuickSort(a, 0, a.Length-1);
//PrintArr(a);
}

you partition method has issue.
you should have it like this.
public static int partition(int[] a, int start, int end)
{
int pivot = a[end];
int i = (start - 1);
for (int j = start; j <= end - 1; j++)
{
if (a[j] < pivot)
{
i++;
swap(a, i, j);
}
}
swap(a, i + 1, end);
return (i + 1);
}

Related

Binary Insertion Sort using recursion - working for one array and not another?

Doing a Binary Insertion Sort and my recursion is backfiring on me when I return my array. When I use the array : { 3, 1, 2, 4 } I get back 1,2,3,4.
When I use the array : { 3, 7, 2, 4 } the recursion causes a StackOverflow.
Where am I going wrong?
p.s Sorry about the console.writelines in my code it helps me check whats going on as I develop
The C# code is per the following snippet:
int[] a = new int[] { 3, 1, 2, 4 }; //Array to be sorted
int MiddlePointer = 0;
int LeftPointer = 0;
int RightPointer = 0;
int i = 1; //First number is 'sorted' so focus on second number
BinaryInsertSort(a, MiddlePointer, LeftPointer, RightPointer, i);
void BinaryInsertSort(int[] a, int MiddlePointer, int LeftPointer, int RightPointer, int i)
{
if (i == a.Length) //This should EXIT the algorithm once all of the numbers are sorted
{
return;
}
if (MiddlePointer == 0 & LeftPointer == 0 & RightPointer == 0) //If this is the first iteration, only the first number is 'sorted' and all of the pointers are the same
{
if (a[i] > a[MiddlePointer]) //If the next number is higher then just raise the RightPointer
{
RightPointer = i;
}
else //If the next number is lower, the 'sorted' values need to be 'shifted' one place to the right
{
RightPointer = i;
int temp = a[i];
for (int j = RightPointer; j > LeftPointer; j--)
{
a[j] = a[j - 1];
}
a[LeftPointer] = temp;
}
// i++; //At this point one number has been sorted
}
else
{
a = Testing(a, MiddlePointer, LeftPointer, RightPointer, i);
}
foreach (int x in a)
{
Console.WriteLine(x);
}
Console.ReadLine();
i++;
BinaryInsertSort(a, MiddlePointer, LeftPointer, RightPointer, i);
}
int[] Testing(int[] a, int MiddlePointer, int LeftPointer, int RightPointer,int i) //This method should find the space where the number should be inserted and return the updated array
{
if(MiddlePointer == RightPointer & RightPointer == LeftPointer)
{
Console.WriteLine($"{a[i]} has not been found");
if (a[i] > a[MiddlePointer])
{
RightPointer = i;
}
else
{
RightPointer = i;
int temp = a[i];
for (int j = RightPointer; j > 0; j--)//move up values
{
a[j] = a[j - 1];
}
a[LeftPointer] = temp;
}
}
else if (a[i] > a[MiddlePointer])
{
Console.WriteLine($"{a[i]} is greater than {a[MiddlePointer]}");
LeftPointer = MiddlePointer + 1;
MiddlePointer = (LeftPointer + RightPointer) / 2;
Testing(a, MiddlePointer, LeftPointer, RightPointer, i);
}
else if (a[i] < a[MiddlePointer])
{
Console.WriteLine($"{a[i]} is less than {a[MiddlePointer]}");
RightPointer = MiddlePointer - 1;
MiddlePointer = (LeftPointer + RightPointer) / 2;
Testing(a, MiddlePointer, LeftPointer, RightPointer, i);
}
return a;
}
Basically I went back to scratch and did a binary search first. This really helped in my previous attempt so I really made sure this worked before moving onto binary insertion sort. From this point I modified the code bit by bit and tried loads of different data sets to see if anything changed. Using breakpoints really helped. I needed to go through and 'follow' the changing variables to see where errors were being made. I also used Console.ReadLine and Console.WriteLine to follow where my logic was ending up. There are many loops in this code and the biggest problem was when I was using the recursion. I was using the recursion to find the 'gap' were the number should be inserted, this was the moment all of the pointers were the same. These pointers needed to constantly be updated and changed at the right moments. This was the most challenging part of the sort.
int i = 1;
int MiddlePointer = 0;
int LeftPointer = 0;
int RightPointer = 0;
BinaryInsertionSort.SortList(UnsortedNumberList, MiddlePointer, LeftPointer, RightPointer, i);
public void SortList(int[] a, int MiddlePointer, int LeftPointer, int RightPointer, int i)
{
if (i == a.Length)
{
Console.Write("Sorted list: ");
for (int x = 0; x < a.Length; x++) //output sorted list
{
if (x == a.Length - 1)
{
Console.Write($"{a[x]}");
}
else
{
Console.Write($"{a[x]}, ");
}
}
return;
}
if (a[MiddlePointer] == a[i])
{
RightPointer = i;
int temp = a[i];
for (int j = i; j > MiddlePointer + 1; j--)
{
a[j] = a[j - 1];
}
a[MiddlePointer + 1] = temp;
LeftPointer = 0;
MiddlePointer = i / 2;
i++;
SortList(a, MiddlePointer, LeftPointer, RightPointer, i);
}
else if (MiddlePointer == RightPointer & RightPointer == LeftPointer)
{
if (a[i] > a[MiddlePointer])
{
RightPointer = i;
int temp = a[i];
for (int j = i; j > MiddlePointer + 1; j--)
{
a[j] = a[j - 1];
}
a[MiddlePointer + 1] = temp;
}
else //If the next number is lower, the 'sorted' values need to be 'shifted' one place to the right
{
RightPointer = i;
int temp = a[i];
for (int j = i; j > MiddlePointer; j--)
{
a[j] = a[j - 1];
}
a[MiddlePointer] = temp;
}
LeftPointer = 0;
MiddlePointer = i / 2;
i++;
SortList(a, MiddlePointer, LeftPointer, RightPointer, i);
}
else if (a[i] > a[MiddlePointer])
{
LeftPointer = MiddlePointer + 1;
if (LeftPointer > RightPointer)
{
LeftPointer = RightPointer;
}
MiddlePointer = (LeftPointer + RightPointer) / 2;
SortList(a, MiddlePointer, LeftPointer, RightPointer, i);
}
else if (a[i] < a[MiddlePointer])
{
RightPointer = MiddlePointer - 1;
if (RightPointer < 0)
{
RightPointer = 0;
}
MiddlePointer = (LeftPointer + RightPointer) / 2;
SortList(a, MiddlePointer, LeftPointer, RightPointer, i);
}
}
}
UnsortedNumberList is an array of numbers. At first the pointers point at the first number at Array position 0. When the pointers are equal to each other then the position where the number is inserted has been found. From this point evaluate if the next number is higher or lower that this optimum position. Numbers will have to be juggled about hence the for loops with int j and variable temp. I hope this helps anyone else doing merge sort in the future.

Sorting Neighborhoods by Population Using Heap

I am trying to sort the neighborhoods by their populations. I used heap sorting algorithm in C#. I created an Array which keeps the population of the neighborhoods named "arr". And created an array which keeps the name of the hoods . It works good but how can I get output of sorting with name of the neighborhoods?
My code is here:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace HoodSorting
{
public class example
{
static void heapSort(int[] arr, int n)
{
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);
for (int i = n - 1; i >= 0; i--)
{
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
heapify(arr, i, 0);
}
}
static void heapify(int[] arr, int n, int i)
{
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < n && arr[left] > arr[largest])
largest = left;
if (right < n && arr[right] > arr[largest])
largest = right;
if (largest != i)
{
int swap = arr[i];
arr[i] = arr[largest];
arr[largest] = swap;
heapify(arr, n, largest);
}
}
public static void Main()
{// arr REPRESENTS THE POUPLATION OF THE NEIGHBORHOODS
string[] neighborhoods = { "Bornova" ,"Westriver","Paradise","Goodman","McMountain","Rocker","Summerlin","Northcity","Greenhill","Sevenwaves"};
int[] arr = { 55, 25, 89, 34, 12, 19, 78, 95, 1, 100 };
int n = 10, i;
Console.WriteLine("Heap Sort");
Console.Write("Initial array is: ");
for (i = 0; i < n; i++)
{
Console.Write(arr[i] + " ");
}
heapSort(arr, 10);
Console.Write("\nSorted Array is: ");
for (i = 0; i < n; i++)
{
Console.Write(arr[i] + " ");
}
}
}
}
How can I get output like this:
Sorted Array is: Greenhill, McMountain,....,........, Northcity, Sevenwaves
Thanks a lot for the help
From an OOP perspective you would keep the two properties (name and population of a neighborhood) together in one object. Then when you sort the objects, you'll still have the associated data right there.
There are several ways to do this. For instance, you could create tuples.
Here is how that is applied to your code:
static void heapSort(Tuple<int, string>[] arr)
{
int n = arr.Length;
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);
for (int i = n - 1; i >= 0; i--)
{
(arr[0], arr[i]) = (arr[i], arr[0]);
heapify(arr, i, 0);
}
}
static void heapify(Tuple<int, string>[] arr, int n, int i)
{
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < n && arr[left].Item1 > arr[largest].Item1)
largest = left;
if (right < n && arr[right].Item1 > arr[largest].Item1)
largest = right;
if (largest != i)
{
(arr[i], arr[largest]) = (arr[largest], arr[i]);
heapify(arr, n, largest);
}
}
public static void Main()
{
Tuple<int, string>[] arr = {
Tuple.Create(55, "Bornova"),
Tuple.Create(25, "Westriver"),
Tuple.Create(89, "Paradise"),
Tuple.Create(34, "Goodman"),
Tuple.Create(12, "McMountain"),
Tuple.Create(19, "Rocker"),
Tuple.Create(78, "Summerlin"),
Tuple.Create(95, "Northcity"),
Tuple.Create(1, "Greenhill"),
Tuple.Create(100, "Sevenwaves")
};
Console.WriteLine("Initial array is: ");
foreach (var pair in arr)
{
Console.Write(pair.Item2 + " ");
}
Console.WriteLine();
heapSort(arr);
Console.WriteLine("Sorted Array is: ");
foreach (var pair in arr)
{
Console.Write(pair.Item2 + " ");
}
Console.WriteLine();
}

returns the smallest positive integer (greater than 0) that does not occur in Array

I have the following question:-
Write a function:
class Solution { public int solution(int[] A); }
that, given an array A of N integers, returns the smallest positive integer (greater than 0) that does not occur in A.
For example, given A = [1, 3, 6, 4, 1, 2], the function should return 5.
Given A = [1, 2, 3], the function should return 4.
Given A = [−1, −3], the function should return 1.
Write an efficient algorithm for the following assumptions:
N is an integer within the range [1..100,000];
each element of array A is an integer within the range [−1,000,000..1,000,000].
now i tried this code:-
using System;
// you can also use other imports, for example:
// using System.Collections.Generic;
// you can write to stdout for debugging purposes, e.g.
// Console.WriteLine("this is a debug message");
class Solution
{
public int solution(int[] A)
{
// write your code in C# 6.0 with .NET 4.5 (Mono)
int n = 1;
Array.Sort(A);
for (int i = 1; i <= 100000; i++)
{
for (int i2 = 0; i2 <= A.Length - 1; i2++)
{
if (A[i2] == i)
{
n = A[i2] + 1;
break;
}
}
}
return n;
}
}
where my code worked well for these test data:-
A = [1, 2, 3]
A = [−1, −3]
while failed for this one:-
A = [1, 3, 6, 4, 1, 2] where it return 7 instead of 5.
any advice why my code failed on the 3rd test?
Thanks
using System.Linq;
int smallestNumber = Enumerable.Range(1, 100000).Except(A).Min();
I would use following approach that uses a HashSet<int> to check if a given integer is missing:
public static int? SmallestMissing(int[] A, int rangeStart = 1, int rangeEnd = 100_000)
{
HashSet<int> hs = new HashSet<int>(A);
for (int i = rangeStart; i <= rangeEnd; i++)
if(!hs.Contains(i)) return i;
return null;
}
A HashSet is a collection if unique values and it's very efficient in lookup items(complexity is O(1)). So you get a very readable and efficient algorithm at the cost of some memory.
Maybe you could optimize it by providing another algorithm in case the array is very large, you don't want to risk an OutOfMemoryException:
public static int? SmallestMissing(int[] A, int rangeStart = 1, int rangeEnd = 100_000)
{
if(A.Length > 1_000_000)
{
Array.Sort(A);
for (int i = rangeStart; i <= rangeEnd; i++)
{
int index = Array.BinarySearch(A, i);
if(index < 0) return i;
}
return null;
}
HashSet<int> hs = new HashSet<int>(A);
for (int i = rangeStart; i <= rangeEnd; i++)
if(!hs.Contains(i)) return i;
return null;
}
If you're allowed to sort the array in-place, which means modifying the input parameter value, here's a simple linear probe for the missing value (on top of the sort of course).
Here's the pseudo-code:
Sort the array
Skip all negatives and 0's at the start
Loopify the following:
Expect 1, if not found at current location return 1
Skip all 1's
Expect 2, if not found at current location return 2
Skip all 2's
Expect 3, if not found at current location return 3
Skip all 3's
... and so on for 4, 5, 6, etc. until end of array
If we get here, return currently expected value which should've been at the end
Here's the code:
public static int FirstMissingValue(int[] input)
{
Array.Sort(input);
int index = 0;
// Skip negatives
while (index < input.Length && input[index] < 1)
index++;
int expected = 1;
while (index < input.Length)
{
if (input[index] > expected)
return expected;
// Skip number and all duplicates
while (index < input.Length && input[index] == expected)
index++;
expected++;
}
return expected;
}
Test-cases:
Console.WriteLine(FirstMissingValue(new[] { 1, 3, 6, 4, 1, 2 }));
Console.WriteLine(FirstMissingValue(new[] { 1, 2, 3 }));
Console.WriteLine(FirstMissingValue(new[] { -1, -3 }));
output:
5
4
1
Your alg won't work in case input array becomes like this: [1,2-1,1,3,5]. I did this based on your alg. Give it a try:
int[] a = new int[] { -1, -2};
IEnumerable<int> uniqueItems = a.Distinct<int>().Where(x => x > 0);
if (uniqueItems.Count() == 0)
{
Console.WriteLine("result: 1");
}
else
{
Array asList = uniqueItems.ToArray();
Array.Sort(asList);
for (int i = 1; i <= 100000; i++)
{
if ((int)asList.GetValue(i - 1) != i)
{
Console.WriteLine("result: " + i);
break;
}
}
}
you can try like this.
public static int solution(int[] A)
{
int smallest = -1;
Array.Sort(A);
if(A[0] > 1)
return 1;
for(int i = 0; i < A.Length; i++)
{
if(A.Length != i+1 && A[i] + 1 != A[i + 1] && A[i+1] > 0)
{
smallest = A[i]+1;
break;
}
else if(A[i] > 0 && A.Length == i+1)
{
smallest = A[i] + 1;
}
}
return smallest > 0 ? smallest:1;
}
Here's the approach that uses O(N) partitioning followed by an O(N) search. This approach does not use any additional storage, but it DOES change the contents of the array.
This code was converted from here. Also see this article.
I've added comments to try to explain how the second stage findSmallestMissing() works. I've not commented the partitioning method, since that's just a variant of a standard partition as might be used in a QuickSort algorithm.
static class Program
{
public static void Main()
{
Console.WriteLine(FindSmallestMissing(1, 3, 6, 4, 1, 2));
Console.WriteLine(FindSmallestMissing(1, 2, 3));
Console.WriteLine(FindSmallestMissing(-1, -3));
}
public static int FindSmallestMissing(params int[] array)
{
return findSmallestMissing(array, partition(array));
}
// Places all the values > 0 before any values <= 0,
// and returns the index of the first value <= 0.
// The values are unordered.
static int partition(int[] arr)
{
void swap(int x, int y)
{
var temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
int pIndex = 0; // Index of pivot.
for (int i = 0; i < arr.Length; i++)
{
if (arr[i] > 0) // pivot is 0, hence "> 0"
swap(i, pIndex++);
}
return pIndex;
}
// This is the clever bit.
// We will use the +ve values in the array as flags to indicate that the number equal to that index is
// present in the array, by making the value negative if it is found in the array.
// This way we can store both the original number AND whether or not the number equal to that index is present
// in a single value.
//
// Given n numbers that are all > 0, find the smallest missing number as follows:
//
// For each array index i in (0..n):
// val = |arr[i]| - 1; // Subtract 1 so val will be between 0 and max +ve value in original array.
// if (val is in range) // If val beyond the end of the array we can ignore it
// and arr[val] is non-negative // If already negative, no need to make it negative.
// make arr[val] negative
//
// After that stage, we just need to find the first positive number in the array, which indicates that
// the number equal to that index + 1 is missing.
// n = number of values at the start of the array that are > 0
static int findSmallestMissing(int[] arr, int n)
{
for (int i = 0; i < n; i++)
{
int val = Math.Abs(arr[i]) - 1;
if (val < n && arr[val] >= 0)
arr[val] = -arr[val];
}
for (int i = 0; i < n; i++)
{
if (arr[i] > 0) // Missing number found.
return i + 1;
}
return n + 1; // No missing number found.
}
}
class Program
{
static void Main(string[] args)
{
int [] A = new int[] {1, 2, 3};
int n = 0;
bool found = false;
Array.Sort(A);
for (int i = 1; i <= 100000; i++) {
for (int x = 0; x <= A.Length - 1; x++) {
int next = (x + 1) < A.Length ? (x + 1): x;
if (A[x] > 0 && (A[next] - A[x]) > 0) {
n = A[x] + 1;
found = true;
break;
}
}
if(found) {
break;
}
}
Console.WriteLine("Smallest number: " + n);
}
}
int smallestNumber=Enumerable.Range(1,(int.Parse(A.Length.ToString())+1)).Except(A).Min();
Array.Sort(A);
for (int number = 1; number <= 100000; number++)
{
for (int num = number; i2 <= A.Length - 1; num++)
{
if (A[num] == number)
{
smallestNumber = A[num] + 1;
break;
}
}
}
return smallestNumber;
}
The easiest one :)
class Solution
{
public int solution(int[] array)
{
int[] onlyPositiveArray = array.Where(a => a > 0).OrderBy(a => a).Distinct().ToArray();
int smallestNumber = 1;
foreach (var number in onlyPositiveArray)
{
if (smallestNumber != number)
{
break;
}
smallestNumber ++;
}
if (!onlyPositiveArray.Contains(smallestNumber ))
{
return smallestNumber;
}
else
{
return smallestNumber + 1;
}
}
}
PHP Solution:
function solution($A) {
// write your code in PHP7.0
// sort array
sort($A);
// get the first
$smallest = $A[0];
// write while
while( in_array(($smallest),$A) || (($smallest) < 1 ) )
{
$smallest++;
}
return $smallest;
}
My solution, also if someone could test how performant it is?
public int solution(int[] N) {
if (N.Length == 0)
return 1;
else if (N.Length == 1)
return N[0] >= 0 ? N[0] + 1 : 1;
Array.Sort(N);
int min = Array.Find(N, IsUnderZero);
if (min ==
default)
return 1;
HashSet < int > hashSet = new HashSet < int > (N);
int max = N[N.Length - 1];
for (int i = min + 1; i <= max + 1; i++) {
if (!hashSet.Contains(i) && i > 0)
return i;
}
return max + 1;
bool IsUnderZero(int i) => i <= 0;
}
Try the below:
public static int MinIntegerGreaterThanZeroInArray(int[] A)
{
int minInt;
if (A.Length > 0)
{
Array.Sort(A);
for (minInt = 1; minInt <= A.Length; minInt++)
{
int index = Array.BinarySearch(A, minInt);
if (index < 0) return minInt;
}
return minInt;
}
//Array is empty.
throw new InvalidOperationException();
}
public static int Smallest(int[] A)
{
int maxPositiveInt = 1;
HashSet<int> NumDic = new HashSet<int>();
for (int i = 0; i < A.Length; i++)
{
if (A[i] <= 0)
{
continue;
}
if (!NumDic.Contains(A[i]))
{
NumDic.Add(A[i]);
}
maxPositiveInt = Math.Max(A[i], maxPositiveInt);
}
//All numbers are negative
if (NumDic.Count == 0)
{
return 1;
}
int smallestinteger = 1;
for (int i = 0; i < A.Length; i++)
{
if (A[i] <= 0)
{
continue;
}
if (!NumDic.Contains(smallestinteger))
{
return smallestinteger;
}
else
{
smallestinteger++;
}
}
return maxPositiveInt + 1;
}
static void Main(string[] args)
{
Console.WriteLine(solution(new int[]{1, 3, 6, 4, 1, 2}));
}
public static int solution(int[] A)
{
Array.Sort(A);
int smallest = A[0];
while (A.Contains(smallest+1)|| (smallest+1)<1)
{
smallest++;
}
return smallest +1;
}

Why does my merge sort algorithm not sort my array correctly?

I am currently triyng to sort some intergers with Merge Sort, but something is wrong with my algoritm.
I have a larger file with integers Im supposed to sort, but I use a smaller, given array to check if its working before sorting the larger file.
My Output from THIS algoritm is: 1 2 2 2 4 5 6, but it's supposed to be: 1 2 4 5 6 9 10 ??
Here's what I've got:
private static int[] data = new int[] { 1, 9, 10, 2, 4, 5, 6 };
static void Main(string[] args)
{
int N = data.Length;
Sort(data, 0, N - 1);
for (int i = 0; i < N; i++)
Console.WriteLine(data[i]);
}
private static void Merge(int[] intArray, int lo, int mid, int hi)
{
int i = lo;
int j = mid + 1;
if (intArray.Length != 0)
for (int k = lo; k <= hi; k++)
data[k] = intArray[k];
for (int k = lo; k <= hi; k++)
{
if (i > mid)
intArray[k] = data[j++];
else if (j > hi)
intArray[k] = data[i++];
else if (data[j] < data[i])
intArray[k] = data[j++];
else if (data[i] < data[j])
intArray[k] = data[i++];
}
}
private static void Sort(int[] intArray, int lo, int hi)
{
if (hi <= lo)
return;
int mid = lo + (hi - lo) / 2;
Sort(intArray, lo, mid);
Sort(intArray, mid + 1, hi);
Merge(intArray, lo, mid, hi);
}
I think the problem is in array reference in C# as #canton7 said, try this code:
private static int[] data = new int[] { 1, 9, 10, 2, 4, 5, 6 };
private static int[] intArray;
static void Main()
{
int N = data.Length;
intArray = new int[N];
Sort(0, N - 1);
for (int i = 0; i < N; i++)
Console.WriteLine(intArray[i]);
}
private static void Merge(int lo, int mid, int hi)
{
int i = lo;
int j = mid + 1;
for (int k = lo; k <= hi; k++)
{
if (i > mid)
intArray[k] = data[j++];
else if (j > hi)
intArray[k] = data[i++];
else if (data[j] < data[i])
intArray[k] = data[j++];
else if (data[i] < data[j])
intArray[k] = data[i++];
}
if (intArray.Length != 0)
for (int k = lo; k <= hi; k++)
data[k] = intArray[k];
}
private static void Sort(int lo, int hi)
{
if (hi == lo)
return;
int mid = lo + (hi - lo) / 2;
Sort(lo, mid);
Sort(mid + 1, hi);
Merge(lo, mid, hi);
}

Implementing quicksort algorithm

I found quicksort algorithm from this book
This is the algorithm
QUICKSORT (A, p, r)
if p < r
q = PARTITION(A, p, r)
QUICKSORT(A, p, q-1)
QUICKSORT(A, q+1, r)
PARTITION(A, p, r)
x=A[r]
i=p-1
for j = p to r - 1
if A <= x
i = i + 1
exchange A[i] with A[j]
exchange A[i+1] with A[r]
return i + 1
And I made this c# code:
private void quicksort(int[] input, int low, int high)
{
int pivot_loc = 0;
if (low < high)
pivot_loc = partition(input, low, high);
quicksort(input, low, pivot_loc - 1);
quicksort(input, pivot_loc + 1, high);
}
private int partition(int[] input, int low, int high)
{
int pivot = input[high];
int i = low - 1;
for (int j = low; j < high-1; j++)
{
if (input[j] <= pivot)
{
i++;
swap(input, i, j);
}
}
swap(input, i + 1, high);
return i + 1;
}
private void swap(int[] ar, int a, int b)
{
temp = ar[a];
ar[a] = ar[b];
ar[b] = temp;
}
private void print(int[] output, TextBox tbOutput)
{
tbOutput.Clear();
for (int a = 0; a < output.Length; a++)
{
tbOutput.Text += output[a] + " ";
}
}
When I call function like this quicksort(arr,0,arr.Length-1); I get this error An unhandled exception of type 'System.StackOverflowException' occurred it pass empty array... when call function like this quicksort(arr,0,arr.Length); I get error Index was outside the bounds of the array. on this line int pivot = input[high]; but array passed successfully.
I also want to print it like this print(input,tbQuick); but where to place it so it would print when quicksort finished?
You did not properly implement the base case termination, which causes quicksort to never stop recursing into itself with sublists of length 0.
Change this:
if (low < high)
pivot_loc = partition(input, low, high);
quicksort(input, low, pivot_loc - 1);
quicksort(input, pivot_loc + 1, high);
to this:
if (low < high) {
pivot_loc = partition(input, low, high);
quicksort(input, low, pivot_loc - 1);
quicksort(input, pivot_loc + 1, high);
}
In addition to Deestan's answer, you also have this wrong:
for (int j = low; j < high-1; j++)
It should be:
for (int j = low; j < high; j++)
Just in case you want some shorter code for Quicksort:
IEnumerable<int> QuickSort(IEnumerable<int> i)
{
if (!i.Any())
return i;
var p = (i.First() + i.Last) / 2 //whichever pivot method you choose
return QuickSort(i.Where(x => x < p)).Concat(i.Where(x => x == p).Concat(QuickSort(i.Where(x => x > p))));
}
Get p (pivot) with whatever method is suitable of course.
This is the shortest implementation of Quick Sort algorithm (Without StackOverflowException)
IEnumerable<T> QuickSort<T>(IEnumerable<T> i) where T :IComparable
{
if (!i.Any()) return i;
var p = i.ElementAt(new Random().Next(0, i.Count() - 1));
return QuickSort(i.Where(x => x.CompareTo(p) < 0)).Concat(i.Where(x => x.CompareTo(p) == 0)).Concat(QuickSort(i.Where(x => x.CompareTo(p) > 0)));
}
A Simple Quick Sort Implementation.
https://github.com/bharathkumarms/AlgorithmsMadeEasy/blob/master/AlgorithmsMadeEasy/QuickSort.cs
using System;
using System.Collections.Generic;
using System.Linq;
namespace AlgorithmsMadeEasy
{
class QuickSort
{
public void QuickSortMethod()
{
var input = System.Console.ReadLine();
string[] sInput = input.Split(' ');
int[] iInput = Array.ConvertAll(sInput, int.Parse);
QuickSortNow(iInput, 0, iInput.Length - 1);
for (int i = 0; i < iInput.Length; i++)
{
Console.Write(iInput[i] + " ");
}
Console.ReadLine();
}
public static void QuickSortNow(int[] iInput, int start, int end)
{
if (start < end)
{
int pivot = Partition(iInput, start, end);
QuickSortNow(iInput, start, pivot - 1);
QuickSortNow(iInput, pivot + 1, end);
}
}
public static int Partition(int[] iInput, int start, int end)
{
int pivot = iInput[end];
int pIndex = start;
for (int i = start; i < end; i++)
{
if (iInput[i] <= pivot)
{
int temp = iInput[i];
iInput[i] = iInput[pIndex];
iInput[pIndex] = temp;
pIndex++;
}
}
int anotherTemp = iInput[pIndex];
iInput[pIndex] = iInput[end];
iInput[end] = anotherTemp;
return pIndex;
}
}
}
/*
Sample Input:
6 5 3 2 8
Calling Code:
QuickSort qs = new QuickSort();
qs.QuickSortMethod();
*/
Code Implemented with Iteration With last element as Pivot
<code>https://jsfiddle.net/zishanshaikh/5zxvwoq0/3/ </code>
function quickSort(arr,l,u) {
if(l>=u)
{
return;
}
var pivot=arr[u];
var pivotCounter=l;
for(let i=l;i<u;i++)
{
if(arr[i] <pivot )
{
var temp= arr[pivotCounter];
arr[pivotCounter]=arr[i] ;
arr[i]=temp;
pivotCounter++;
}
}
var temp2= arr[pivotCounter];
arr[pivotCounter]=arr[u] ;
arr[u]=temp2;
quickSort(arr,pivotCounter+1,u);
quickSort(arr,0,pivotCounter-1);
}
<code>https://jsfiddle.net/zishanshaikh/exL9cdoe/1/</code>
Code With first element as Pivot
//Logic For Quick Sort
function quickSort(arr,l,u) {
if(l>=u)
{
return;
}
var pivot=arr[l];
var pivotCounter=l+1;
for(let i=l+1;i<u;i++)
{
if(arr[i] <pivot )
{
var temp= arr[pivotCounter];
arr[pivotCounter]=arr[i] ;
arr[i]=temp;
pivotCounter++;
}
}
var j=pivotCounter-1;
var k=l+1;
while(k<=j)
{
var temp2= arr[k-1];
arr[k-1]=arr[k] ;
arr[k]=temp2;
k++;
}
arr[pivotCounter-1]=pivot;
quickSort(arr,pivotCounter,u);
quickSort(arr,0,pivotCounter-2);
}
A simple generic C# implementation of QuickSort, can use first or last value or any other intermediate value for pivot
using System;
namespace QuickSort
{
class Program
{
static void Main(string[] args)
{
int[] arInt = { 6, 4, 2, 8, 4, 5, 4, 5, 4, 5, 4, 8, 11, 1, 7, 4, 13, 5, 45, -1, 0, -7, 56, 10, 57, 56, 57, 56 };
GenericQuickSort<int>.QuickSort(arInt, 0, arInt.Length - 1);
string[] arStr = { "Here", "Is", "A", "Cat", "Really", "Fast", "And", "Clever" };
GenericQuickSort<string>.QuickSort(arStr, 0, arStr.Length - 1); ;
Console.WriteLine(String.Join(',', arInt));
Console.WriteLine(String.Join(',', arStr));
Console.ReadLine();
}
}
class GenericQuickSort<T> where T : IComparable
{
public static void QuickSort(T[] ar, int lBound, int uBound)
{
if (lBound < uBound)
{
var loc = Partition(ar, lBound, uBound);
QuickSort(ar, lBound, loc - 1);
QuickSort(ar, loc + 1, uBound);
}
}
private static int Partition(T[] ar, int lBound, int uBound)
{
var start = lBound;
var end = uBound;
var pivot = ar[uBound];
// switch to first value as pivot
// var pivot = ar[lBound];
while (start < end)
{
while (ar[start].CompareTo(pivot) < 0)
{
start++;
}
while (ar[end].CompareTo(pivot) > 0)
{
end--;
}
if (start < end)
{
if (ar[start].CompareTo(ar[end]) == 0)
{
start++;
}
else
{
swap(ar, start, end);
}
}
}
return end;
}
private static void swap(T[] ar, int i, int j)
{
var temp = ar[i];
ar[i] = ar[j];
ar[j] = temp;
}
}
}
Output:
-7,-1,0,1,2,4,4,4,4,4,4,5,5,5,5,6,7,8,8,10,11,13,45,56,56,56,57,57
A,And,Cat,Clever,Fast,Here,Is,Really
One important thing to notice here is that this optimized and simple code properly handles duplicates. I tried several posted quick sort code. Those do not give correct result for this (integer array) input or just hangs, such as https://www.w3resource.com/csharp-exercises/searching-and-sorting-algorithm/searching-and-sorting-algorithm-exercise-9.php and http://www.softwareandfinance.com/CSharp/QuickSort_Iterative.html. Therefore, if author also wants to use the code which handles duplicates this would be a good reference.

Categories

Resources