First Element as pivot in Quick sort - c#

Why this code gives me wrong ? In Quick sort , I have picked up the first element as pivot:
I have traced that on paper,nothing is wrong.
private void QuickSort(ref int [] S ,int l,int h)
{
//partioning
int pivot_index = l;
int j = 0;
int temp = 0;
for(int i=l+1;i<=h;i++)
if (S[pivot_index] > S[i])
{
j++;
temp = S[i];
S[i] = S[j];
S[j] = temp;
}
pivot_index = j;
temp = S[l];
S[l] = S[j];
S[j] = temp;
//end partioning
if (l < h && pivot_index>l && pivot_index<h)
{
QuickSort(ref S, l, pivot_index - 1);
QuickSort(ref S, pivot_index + 1, h);
}
}
here is my main :
int[] List = get_input(textBox1.Text, ref n);
//
QuickSort(ref List, 0, n-1);

Your function is apparently supposed to sort [l, h] range in the array, yet for some reason you are swapping element number i with element number j. The latter (j) is out of [l, h] range (it is always initially 0 and then it becomes 1, 2, 3 and so on). What are you trying to do by this? Why are you swapping your elements to some totally unrelated remote location out of your sorting range?
In other words this does not even remotely look like a QuickSort-style sorting algorithm to me. Your unexplainable manipulations with j is one reason why your implementation cannot really sort anything.

Your algorithm is wrong. Get the pivot value int pivot = S[pivot_index];.
Then determine the two elements that you want to swap. Therefore, determine the first element from the left, which is greater than or equal to the pivot value. This gives i. Then determine the first element from the right, which is less than or equal to the pivot value. This gives j. As long as i is less than j swap S[i] and S[j] and repeat the process.
Only after there are no more swaps to make, look if you can call QuickSort recursively. Here two separate if checks must be made for the left part and the right part.
Also, note that it is better to take the element in the middle as pivot element. QuickSort will perform better, if the elements should be pre-sorted or sorted in descending order.
int pivot = S[(l+h)/2];

Related

What sorting method is this being applied and what is the algorithmic complexity of the method

I came across the code below for implementing sorting array.
I have applied to a very long array and it was able to do so in under a sec may be 20 millisec or less.
I have been reading about Algorithm complexity and the Big O notation and would like to know:
Which is the sorting method (of the existing ones) that is implemented in this code.
What is the complexity of the algorithm used here.
If you were to improve the algorithm/ code below what would you alter.
using System;
using System.Text;
//This program sorts an array
public class SortArray
{
static void Main(String []args)
{
// declaring and initializing the array
//int[] arr = new int[] {3,1,4,5,7,2,6,1, 9,11, 7, 2,5,8,4};
int[] arr = new int[] {489,491,493,495,497,529,531,533,535,369,507,509,511,513,515,203,205,207,209,211,213,107,109,111,113,115,117,11913,415,417,419,421,423,425,427,15,17,19,21,4,517,519,521,523,525,527,4,39,441,443,445,447,449,451,453,455,457,459,461,537,539,541,543,545,547,1,3,5,7,9,11,13,463,465,467,23,399,401,403,405,407,409,411,499,501,503,505,333,335,337,339,341,343,345,347,65,67,69,71,73,75,77,79,81,83,85,87,89,91,93,95,9,171,173,175,177,179,181,183,185,187,269,271,273,275,277,279,281,283,25,27,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,61,63,133,135,137,139,141,143,145,285,287,289,291,121,123,125,127,129,131,297,299,373,375,377,379,381,383,385,387,389,97,99,101,103,105,147,149,151,153,155,157,159,161,163,165,167,16,391,393,395,397,399,401,403,189,191,193,195,197,199,201,247,249,251,253,255,257,259,261,263,265,267,343,345,347,349,501,503,505,333,335,337,339,341,417,419,421,423,425,561,563,565,567,569,571,573,587,589,591,593,595,597,599,427,429,431,433,301,303,305,307,309,311,313,315,317,319,321,323,325,327,329,331,371,359,361,363,365,367,369,507,509,511,513,515,351,353,355,57,517,519,521,523,525,527,413,415,405,407,409,411,499,435,437,469,471,473,475,477,479,481,483,485,487,545,547,549,551,553,555,575,577,579,581,583,585,557,559,489,491,493,495,497,529,531,533,535,537,539,541,543,215,217,219,221,223,225,227,229,231,233,235,237,239,241,243,245,293,295};
int temp;
// traverse 0 to array length
for (int i = 0; i < arr.Length ; i++)
{
// traverse i+1 to array length
//for (int j = i + 1; j < arr.Length; j++)
for (int j = i+1; j < arr.Length; j++)
{
// compare array element with
// all next element
if (arr[i] > arr[j]) {
///Console.WriteLine(i+"i before"+arr[i]);
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
//Console.WriteLine("i After"+arr[i]);
}
}
}
// print all element of array
foreach(int value in arr)
{
Console.Write(value + " ");
}
}
}
This is selection sort. It's time complexity is O(𝑛²). It has nested loops over i and j, and you can see these produce every possible set of two indices in the range {0,...,𝑛-1}, where 𝑛 is arr.Length. The number of pairs is a triangular number, and is equal to:
𝑛(𝑛-1)/2
...which is O(𝑛²)
If we stick to selection sort, we can still find some improvements.
We can see that the role of the outer loop is to store in arr[i] the value that belongs there in the final sorted array, and never touch that entry again. It does so by searching the minimum value in the right part of the array that starts at this index 𝑖.
Now during that search, which takes place in the inner loop, it keeps swapping lesser values into arr[i]. This may happen a few times, as it might find even lesser values as j walks to the right. That is a waste of operations, as we would prefer to only perform one swap. And this is possible: instead of swapping immediately, delay this operation. Instead keep track of where the minimum value is located (initially at i, but this may become some j index). Only when the inner loop completes, perform the swap.
There is less important improvement: i does not have to get equal to arr.Length - 1, as then there are no iterations of the inner loop. So the ending condition for the outer loop can exclude that iteration from happening.
Here is how that looks:
for (int i = 0, last = arr.Length - 1; i < last; i++)
{
int k = i; // index that has the least value in the range arr[i..n-1] so far
for (int j = i+1; j < arr.Length; j++)
{
if (arr[k] > arr[j]) {
k = j; // don't swap yet -- just track where the minimum is located
}
}
if (k > i) { // now perform the swap
int temp = arr[i];
arr[i] = arr[k];
arr[k] = temp;
}
}
A further improvement can be to use the inner loop to not only locate the minimum value, but also the maximum value, and to move the found maximum to the right end of the array. This way both ends of the array get sorted gradually, and the inner loop will shorten twice as fast. Still, the number of comparisons remains the same, and the average number of swaps as well. So the gain is only in the iteration overhead.
This is "Bubble sort" with O(n^2). You can use "Mergesort" or "Quicksort" to improve your algorithm to O(n*log(n)). If you always know the minimum and maximum of your numbers, you can use "Digit sort" or "Radix Sort" with O(n)
See: Sorting alrogithms in c#

Every combination of integers between specific range in combination with a list of strings

I have the following problem:
I have three elements a, b and c. And also integers from 0 to 100. How can I get all the possible combinations to look like:
a 0 b 0 c 0
a 1 b 0 c 0
a 0 b 1 c 0
a 0 b 0 c 1
a 1 b 1 c 0
...
a 100 b 100 c 100
and so on? I am using C# but I am rather struggling to find the correct algorithm independently of programming language. Unfortunately I do not really understand carthesian products etc.
You say you want to
find the correct algorithm independently of programming language
So I shall try to answer this using the minimum of programming language features. The example I shall give assumes the programming language has expandable lists, arrays, arrays of arrays and the ability to shallow clone an array. These are common programming features, so hopefully this will be OK.
To solve this problem, you need to produce all the combinations of 3 sets of N integers where each set consists the integers from 0..N-1. (The set of combinations of a set of sets - which is what this is - is called the Cartesian Product of those sets.)
The solution below uses recursion, but we don't need to worry about stack overflow because the stack depth does not exceed the number of sets to combine - in this case, 3. (Normally with recursion you would try to use a stack class to manage it, but that makes the code more complicated.)
How it works:
combine() recursively iterates through all elements of each set, and at each level of recursion it begins processing the elements of the next set.
So the outer level of recursion begins iterating over all the elements of set[0], and for each element it fills in the next item of the current combination with that element.
Then: if that was the last set, the combination is complete and it is output. Otherwise: a recursive call is made to start filling in the elements from the next set.
Once we have all the combinations, we can just iterate through them and intersperse them
with a, b and c as per your requirement.
Putting this together:
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
var sets = createSets(3, 10);
var combinations = Combinations(sets);
foreach (var combination in combinations)
{
Console.WriteLine($"a {combination[0]} b {combination[1]} c {combination[2]}");
}
}
static int[][] createSets(int numSets, int intsPerSet)
{
int[][] sets = new int[numSets][];
// All the sets are the same, so we can just use copies of it rather than create multiples.
int[] oneSet = new int[intsPerSet];
for (int i = 0; i < intsPerSet; ++i)
oneSet[i] = i;
for (int i = 0; i < numSets; ++i)
sets[i] = oneSet;
return sets;
}
public static List<int[]> Combinations(int[][] sets)
{
var result = new List<int[]>();
combine(sets, 0, new int[sets.Length], result);
return result;
}
static void combine(int[][] sets, int set, int[] combination, List<int[]> output)
{
for (int i = 0; i < sets[set].Length; ++i)
{
combination[set] = sets[set][i];
if (set < (sets.Length - 1))
combine(sets, set + 1, combination, output);
else
output.Add((int[])combination.Clone());
}
}
}
}
Notes
This is an inefficient implementation because it returns all the combinations in one huge list. I kept it this way for simplicity (and to reduce the number of program language features required for its implementation). A better solution in C# would be to pass in an Action<int[]> to be called with each combination - then the results wouldn't need to be returned via a huge list.
This doesn't produce the results in the same order as your sample output. I have assumed that this doesn't matter!
A great Linq implementation of the Cartesian Product is presented by Eric Lippert here. I highly recommending reading it!
If the order of the output doesn't matter, this should be enough:
for(int i = 0; i <= 100; i++){
for(int j = 0; j <= 100; j++){
for(int k = 0; k <= 100; k++){
Console.WriteLine($"a {i} b {j} c {k} ");
}
}
}
OUTPUT
a 0 b 0 c 0
a 0 b 0 c 1
a 0 b 0 c 2
a 0 b 0 c 3
...
a 100 b 100 c 100

How to Order By or Sort an integer List and select the Nth element

I have a list, and I want to select the fifth highest element from it:
List<int> list = new List<int>();
list.Add(2);
list.Add(18);
list.Add(21);
list.Add(10);
list.Add(20);
list.Add(80);
list.Add(23);
list.Add(81);
list.Add(27);
list.Add(85);
But OrderbyDescending is not working for this int list...
int fifth = list.OrderByDescending(x => x).Skip(4).First();
Depending on the severity of the list not having more than 5 elements you have 2 options.
If the list never should be over 5 i would catch it as an exception:
int fifth;
try
{
fifth = list.OrderByDescending(x => x).ElementAt(4);
}
catch (ArgumentOutOfRangeException)
{
//Handle the exception
}
If you expect that it will be less than 5 elements then you could leave it as default and check it for that.
int fifth = list.OrderByDescending(x => x).ElementAtOrDefault(4);
if (fifth == 0)
{
//handle default
}
This is still some what flawed because you could end up having the fifth element being 0. This can be solved by typecasting the list into a list of nullable ints at before the linq:
var newList = list.Select(i => (int?)i).ToList();
int? fifth = newList.OrderByDescending(x => x).ElementAtOrDefault(4);
if (fifth == null)
{
//handle default
}
Without LINQ expressions:
int result;
if(list != null && list.Count >= 5)
{
list.Sort();
result = list[list.Count - 5];
}
else // define behavior when list is null OR has less than 5 elements
This has a better performance compared to LINQ expressions, although the LINQ solutions presented in my second answer are comfortable and reliable.
In case you need extreme performance for a huge List of integers, I'd recommend a more specialized algorithm, like in Matthew Watson's answer.
Attention: The List gets modified when the Sort() method is called. If you don't want that, you must work with a copy of your list, like this:
List<int> copy = new List<int>(original);
List<int> copy = original.ToList();
The easiest way to do this is to just sort the data and take N items from the front. This is the recommended way for small data sets - anything more complicated is just not worth it otherwise.
However, for large data sets it can be a lot quicker to do what's known as a Partial Sort.
There are two main ways to do this: Use a heap, or use a specialised quicksort.
The article I linked describes how to use a heap. I shall present a partial sort below:
public static IList<T> PartialSort<T>(IList<T> data, int k) where T : IComparable<T>
{
int start = 0;
int end = data.Count - 1;
while (end > start)
{
var index = partition(data, start, end);
var rank = index + 1;
if (rank >= k)
{
end = index - 1;
}
else if ((index - start) > (end - index))
{
quickSort(data, index + 1, end);
end = index - 1;
}
else
{
quickSort(data, start, index - 1);
start = index + 1;
}
}
return data;
}
static int partition<T>(IList<T> lst, int start, int end) where T : IComparable<T>
{
T x = lst[start];
int i = start;
for (int j = start + 1; j <= end; j++)
{
if (lst[j].CompareTo(x) < 0) // Or "> 0" to reverse sort order.
{
i = i + 1;
swap(lst, i, j);
}
}
swap(lst, start, i);
return i;
}
static void swap<T>(IList<T> lst, int p, int q)
{
T temp = lst[p];
lst[p] = lst[q];
lst[q] = temp;
}
static void quickSort<T>(IList<T> lst, int start, int end) where T : IComparable<T>
{
if (start >= end)
return;
int index = partition(lst, start, end);
quickSort(lst, start, index - 1);
quickSort(lst, index + 1, end);
}
Then to access the 5th largest element in a list you could do this:
PartialSort(list, 5);
Console.WriteLine(list[4]);
For large data sets, a partial sort can be significantly faster than a full sort.
Addendum
See here for another (probably better) solution that uses a QuickSelect algorithm.
This LINQ approach retrieves the 5th biggest element OR throws an exception WHEN the list is null or contains less than 5 elements:
int fifth = list?.Count >= 5 ?
list.OrderByDescending(x => x).Take(5).Last() :
throw new Exception("list is null OR has not enough elements");
This one retrieves the 5th biggest element OR null WHEN the list is null or contains less than 5 elements:
int? fifth = list?.Count >= 5 ?
list.OrderByDescending(x => x).Take(5).Last() :
default(int?);
if(fifth == null) // define behavior
This one retrieves the 5th biggest element OR the smallest element WHEN the list contains less than 5 elements:
if(list == null || list.Count <= 0)
throw new Exception("Unable to retrieve Nth biggest element");
int fifth = list.OrderByDescending(x => x).Take(5).Last();
All these solutions are reliable, they should NEVER throw "unexpected" exceptions.
PS: I'm using .NET 4.7 in this answer.
Here there is a C# implementation of the QuickSelect algorithm to select the nth element in an unordered IList<>.
You have to put all the code contained in that page in a static class, like:
public static class QuickHelpers
{
// Put the code here
}
Given that "library" (in truth a big fat block of code), then you can:
int resA = list.QuickSelect(2, (x, y) => Comparer<int>.Default.Compare(y, x));
int resB = list.QuickSelect(list.Count - 1 - 2);
Now... Normally the QuickSelect would select the nth lowest element. We reverse it in two ways:
For resA we create a reverse comparer based on the default int comparer. We do this by reversing the parameters of the Compare method. Note that the index is 0 based. So there is a 0th, 1th, 2th and so on.
For resB we use the fact that the 0th element is the list-1 th element in the reverse order. So we count from the back. The highest element would be the list.Count - 1 in an ordered list, the next one list.Count - 1 - 1, then list.Count - 1 - 2 and so on
Theorically using Quicksort should be better than ordering the list and then picking the nth element, because ordering a list is on average a O(NlogN) operation and picking the nth element is then a O(1) operation, so the composite is O(NlogN) operation, while QuickSelect is on average a O(N) operation. Clearly there is a but. The O notation doesn't show the k factor... So a O(k1 * NlogN) with a small k1 could be better than a O(k2 * N) with a big k2. Only multiple real life benchmarks can tell us (you) what is better, and it depends on the size of the collection.
A small note about the algorithm:
As with quicksort, quickselect is generally implemented as an in-place algorithm, and beyond selecting the k'th element, it also partially sorts the data. See selection algorithm for further discussion of the connection with sorting.
So it modifies the ordering of the original list.

How to find common smallest number in two arrays

I have two arrays that I need to sort and find the lowest number that occurs in both arrays. If there is no equality then it should return -1, if there is equality then it should return that number.
Here is my the code I have got so far
public int solution(int[] A, int[] B)
{
int minA = A.Min();// Get minimum number of array A
int minB = B.Min();// Get minimum number of array B
if (minA == minB)// If both arrays have the same smallest number
return minA;
else
return -1;
}
The problem is it is only checking for equality of the lowest number and if it does not match then it returns. How do I get it to look at the next lowest number?
I think you are trying to get the common minimum number (Intersection). So you can use Intersect in this case.
int[] arrA = {100, 102, 99, 107};
int[] arrB = {103, 102, 99, 105, 106, 109};
var commonNumbers = arrA.Intersect(arrB).ToArray();
return commonNumbers.Any() ? commonNumbers.Min() : -1);
I think the best way to approach this problem is to sort the array first, you should try:
public int solution(int[] A, int[] B)
{
//Sorts the array
Array.Sort(A)
Array.Sort(B)
//store the array positions
int j = 0;
int i = 0;
While(i < Array.Length(A) && j < Array.Length(B)) //If any array ends before finding the equality, the while ends and the code return -1;
{
if(A[i] == B[j])
{
return A[i];
}
//if the element from A is larger than the element from B, you have to go up an element in B
if(A[i] > B[j])
{
j++;
}
//if the element from B is larger than the element from A, you have to go up an element in A
if(A[i] < B[j])
{
i++;
}
}
return -1;
}
I didn't tested, but think it should work.
You may try this:
public int solution(int[] A, int[] B)
{
var common = A.Intersect(B).ToList();
return common.Count > 0 ? common.Min() : -1;
}
In pseudocode:
sort array A in ascending order
sort array B in ascending order
set elementB to the first element in B
for all elements in A
if (elementA == elementB)
return elementA
while (elementA > elementB)
try to get the next element from B
if there are no more elements in B
return -1
if (elementA == elementB)
return elementA
end while
// elementA is less than elementB
end for
return -1
In English:
Go through the A list and compare each value with the current value in B. If they match, we're done.
If the value in B is smaller than A, then get the next value from B (because the numbers are sorted from small to large, there will never be a B value that matches the current A).
Keep grabbing the next B value until it is equal to A (we're done) or it is bigger than A (we need to grab the next A value to see if it catches up with the new B).
If we hit the end of either list, there are no matches.
The problem is search the both pre-minimum and then compare, this solution is without pre-sorting, optimizing CPU and memory:
public int solution(int[] A, int[] B)
{
//NOTE: Assumption that the array contains at least 2 values, check & handle the different cases properly
//Take the first 2 values in order
if(A[0]<A[1]){
minA=A[0];
minA2=A[1];
}else{
minA=A[1];
minA2=A[0];
}
//Take the first 2 values in order
if(B[0]<B[1]){
minB=B[0];
minB2=B[1];
}else{
minB=B[1];
minB2=B[0];
}
//Select the minimum and second minimum of A
for(int i=0;i<A.Length;i++){
if(minA>=A[i]){
minA2=minA;//The previous minimum become the second minimum
minA=A[i];
}else if(minA2>A[i]){
minA2=A[i];//A[i] is the actual second minimum
}
}
//Select the minimum and second minimum of B
for(int i=0;i<B.Length;i++){
if(minB>=B[i]){
minB2=minB;//The previous minimum become the second minimum
minB=A[i];
}else if(minB2>B[i]){
minB2=B[i];//B[i] is the actual second minimum
}
}
//Do your comparison
return (minA==minB&&minA2==minB2)?minB2:-1;
//NOTE: if you want to check only the second lower: return minA2==minB2?minB2:-1;
}
Here is my solution in python.
#Solution 1
def solution(A, B):
commonList = [n for n in B if n in A]
commonList.sort()
if len(commonList) > 0:
return commonList[0]
return -1
#Solution 2
def solution(A, B):
commonList = []
for n in A: #Iterates through A and check the elements that appear in B
if n in B:
commonList.append(n)
commonList.sort()
#Sort list in order to get minimum value in the first index.
#you could use min(commonList) too
if len(commonList) > 0:
return commonList[0]
return -1

How to display all members of a given subsequence on the console?

I'm trying to understand why I can't print only the members of a subsequence of an array, that is equal to an integer from the input. The array is also read from the console. When i run the program only the first of these members does come up, but with him also a seemingly random number of zeros, while the rest of the subsequence is omitted. If there's a better way than to use a second array, I'll be grateful if you share it. Okay, to specify- I want to know how to print all the members of the aforementioned subsequence, can you please give me a useful advice or sample? Here's the input, output and code:
4 4 56 57 58
8
4 0 0 0 0
instead of 4 4
int v = int.Parse(Console.ReadLine());
int[] valueHolder = new int[arr1.Length];
int currentSum = 0;
for (int endIndex = 0; endIndex <= arr1.Length -1; endIndex++)
{
currentSum = 0;
for (int currentSumIndex = endIndex; currentSumIndex >= 0; currentSumIndex--)
{
currentSum += arr1[currentSumIndex];
if (currentSum == v)
{
valueHolder[currentSumIndex] = arr1[currentSumIndex];
}
if (currentSum == v)
{
for (int i = 0; i <= valueHolder.Length - 1; i++)
{
Console.Write(valueHolder[i] + " ");
}
}
}
I think you would be best served by putting a break point on the line of the first for loop then stepping through your code. If you take a pad of paper and write each of the variables states as you go through it then it will be pretty obvious what's going on.
However, just to help you out.
In the first pass of the outer loop (endIndex = 0), the inner loop does NOT execute. currentSumIndex = endIndex which equals zero, which does not pass the currentSumIndex >= 0 test. Therefore the first 4 is skipped.
In the second pass, the number 4 is emitted because currentSum equals 4. However, the values of 0 are also emitted because you are walking the entire valueHolder array and spitting all of the empty values out.
From the third pass forward, currentSum will never equal the number you typed in:
The first pass of the inner loop sets currentSum to 56, which does not equal v. The second pass of the inner loops sets it to 56+4 ( currentSum += arr1[currentSumIndex] ) which is 60. Therefore, nothing will ever be emitted again as currentSum will always be the sum of all numbers from the current array position going backward to the beginning array position and therefore will always be greater than v
You don't need a second array. You just need to pay attention to what your code is doing. Side note: I have absolutely no idea why you have that inner loop or even what the 8 is supposed to represent in your example entry above.
If I was writing this, I'd change it to (assuming you can't use LINQ):
int v = int.Parse(Console.ReadLine());
for (int i= 0; i <= arr1.Length -1; i++)
{
if (arr1[i] == v) {
Console.Write(arr1[i].ToString() + " ");
}
}
Console.WriteLine();

Categories

Resources