Quicksort 3 way partition too slow - c++

I am using quicksort 3 way partition, but it is turning out to be too slow as and when the vector size is greater than 10000.
What am I doing wrong? Please guide me! Any help will be appreciated
The answer should be computed in less than 2.2 sec.
#include <iostream>
#include <vector>
#include <cstdlib>
#include <algorithm>
using std::vector;
using std::swap;
void print(vector<int> v)
{
for(int i = 0; i < v.size(); i++) std::cout << v[i] << " ";
std::cout << std::endl;
}
void partition2(vector<int> &a, int l, int r, int &i, int &j) {
int k;
int middle=(l+r)/2;
/*Selecting pivot as median of low, high and middle*/
if(((a[l]<=a[middle]) && (a[middle]<=a[r])) || ((a[r]<=a[middle]) && (a[middle]<=a[l])))
k=middle;
else if(((a[middle]<=a[l]) && (a[l]<=a[r])) || ((a[r]<=a[l]) && (a[l]<=a[middle])))
k=l;
else if(((a[middle]<=a[r]) && (a[r]<=a[l])) || ((a[l]<=a[r]) && (a[r]<=a[middle])))
k=r;
swap(a[l], a[k]);
//print(a);
int low_value = a[l];
int index_low = l;
int index_high = l;
int counter=l;
for (int i = l + 1; i <= r; i++) {
if (a[i] < low_value) {
swap(a[i], a[index_low]);
counter++;
low_value=a[l];
}
else if(a[i]==low_value)
{
index_high++;
swap(a[i], a[index_high]);
}
//print(a);
}
i=counter;
j=index_high;
//swap(a[l], a[j]);
//return j;
}
void randomized_quick_sort(vector<int> &a, int l, int r) {
if (l >= r) {
return;
}
int i,j;
partition2(a, l, r, i, j);
randomized_quick_sort(a, l, i-1);
randomized_quick_sort(a, j+1, r);
}
int main() {
int n;
std::cin >> n;
//while(1){
//n=100+rand()%99999;
//std::cout<<n<<std::endl;
vector<int> a(n);
for (size_t i = 0; i < a.size(); ++i) {
std::cin >> a[i];
//a[i]=1+rand()%99999999;
}
randomized_quick_sort(a, 0, a.size() - 1);
for (size_t i = 0; i < a.size(); ++i) {
std::cout << a[i] << ' ';
}
//std::cout<<"Pass\n";
//}
return 0;
}

Everything at first glance is correct. However, there are probably just too many comparison operations. Try this option - it works on my computer for 1.6 seconds on average.
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <ctime>
#include <random>
#include <chrono>
#include <iomanip>
using namespace std;
using namespace std::chrono;
//======= quick_sort =======//
template<typename T>
int partition(vector<T>& numbers, const int& left, const int& right)
{
swap(numbers[left], numbers[left + (right - left) / 2]);
T mid = numbers[left];
int i(left + 1), j(right);
while (i <= j)
{
while ( i <= j && numbers[i] <= mid ) i++;
while ( i <= j && numbers[j] > mid ) j--;
if ( i < j ) swap(numbers[i], numbers[j]);
}
swap(numbers[i - 1], numbers[left]);
return i - 1;
}
template<typename T>
void quick_sort_rec(vector<T>& numbers, const int& left, const int& right)
{
if (left >= right) return;
int p = partition(numbers, left, right);
quick_sort_rec(numbers, left , p - 1);
quick_sort_rec(numbers, p + 1 , right);
}
//=========================//
template<typename T>
T random_T(long min, long max)
{
return (T)min + static_cast<T>(rand()) / (static_cast<T>(RAND_MAX / ((T)(max - min))));
}
template<typename T>
float time_func(void (*f)(vector<T>&, const int&, const int&), vector<T>& a)
{
high_resolution_clock::time_point t1 = high_resolution_clock::now();
f(a, 0, a.size() - 1);
high_resolution_clock::time_point t2 = high_resolution_clock::now();
return 1000.0 * (duration_cast<microseconds>(t2 - t1).count()) / (float)(CLOCKS_PER_SEC); /// CLOCKS_PER_SEC;
}
int main()
{
srand((unsigned)(777));
vector<int> a;
for (int i = 0; i < 10000; i++)
{
a.push_back(random_T<int>(0, 1000));
}
cout << setprecision(10) << "quick sort rec = " << time_func(quick_sort_rec, a) << endl;
return 0;
}

I run the following code to test partition2
int main(){
vector<int> a = {2, 1, 1, 9, 5, 3, 4, 2, 7};
int i, j;
partition2(a, 0, a.size() - 1, i, j);
for (auto i : a)
cout << i << ' ';
cout << '\n';
return 0;
}
And the results are
1 1 5 9 2 3 4 2 7
If the partition2 selecting median of low, high and middle as pivot, then the pivot should be 5 and the results should be something like
2 1 1 3 4 2 5 9 7
Then I check the code
if (a[i] < low_value) {
swap(a[i], a[index_low]);
counter++;
low_value=a[l];
}
else if(a[i]==low_value)
{
index_high++;
swap(a[i], a[index_high]);
}
It seems to be that the code try to find the minimum value of array and then move them to beginning of array. It seems that it is doing selection sort instead of quicksort. It explains why it is slow when input size is large.

Related

Merge Sort C++ Incorrectly Sorting

I'm writing a program that will do 5 different sorting functions and compare times across them. I'm outputting the 1000th element of each array to see if it's sorted correctly, all of my other sorts except merge sort are producing the correct number. Merge sort is close but off, it is within an element or two of getting the correct answer (outputting 25011 rather than 25034 for the 1000th element.) Here is the code for my merge sort:
//Zach Heesaker. CS3. Project 4
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <stdio.h>
#include <ctime>
#include <cstdio>
#include <time.h>
#include <stdint.h>
#include<list>
#include<cmath>
using namespace std;
const int n = 10000;
int numswaps, numcompares;
void swap(int& a, int& b);
void print(int arr[], int n, ofstream& outf, double time);
void read(int arr[], int size);
void mergepass(int arr[], int y[], int& n, int& L);
void mergeSort(int arr[], int n);
void merge(int arr[], int y[], int L, int m, int n);
int main()
{
int numsorts = 5;
string whichsort;
ofstream outf("output.ot");
int arr[n + 1];
clock_t start, end;
double time;
outf << "Sort Name: " << setw(5) << " " << "1000th Element: " << setw(1) << " " << "Number of Moves: " << setw(1) << " " << "Time taken: " << endl;
read(arr, n);
numcompares = 0;
numswaps = 0;
start = clock();
mergeSort(arr, n);
end = clock();
time = double(end - start) / double(CLOCKS_PER_SEC);
}
void mergeSort(int arr[], int size)
{
int L = 1;
int y[n + 1];
while (L < n)
{
mergepass(arr, y, size, L);
L = 2 * L;
mergepass(y, arr, size, L);
L = 2 * L;
}
}
void merge(int arr[], int y[], int L, int m, int n)
{
int i, j, k, t;
i = L;
k = L;
j = m + 1;
while ((i <= m) && (j <= n))
{
numcompares++;
if (arr[i] <= arr[j])
{
numswaps++;
y[k++] = arr[i++];
}
else
{
numswaps++;
y[k++] = arr[j++];
}
}
if (i > m)
{
for (t = j; t <= n; t++)
{
numswaps++;
y[k + t - j] = arr[t];
}
}
else
{
for (t = i; t <= m; t++)
{
numswaps++;
y[k + t - i] = arr[t];
}
}
}
void mergepass(int arr[], int y[], int& n, int& L)
{
int i, t;
i = 1;
while (i <= n - 2 * L + 1)
{
merge(arr, y, i, i + L - 1, i + 2 * L - 1);
i = i + 2 * L;
}
if ((i + L - 1) < n)
{
merge(arr, y, i, i + L - 1, n);
}
else
{
for (t = i; t <= n; t++)
{
numswaps++;
y[t] = arr[t];
}
}
}
void swap(int& a, int& b)
{
int temp;
temp = a;
a = b;
b = temp;
numswaps += 3;
}
void print(int arr[], int n, ofstream& outf, double time)
{
outf << left << setw(6) << " " << left << arr[1000] << setw(12) << " " << left << numswaps << setw(10) << " " << left << "\t" << time << endl;
}
void read(int arr[], int size)
{
ifstream ifs("input.txt");
int i = 0;
while (!ifs.eof())
{
ifs >> arr[i];
i++;
}
}
int merge(int arr[], int left, int right)
{
int pivot = arr[right];
int k = (left - 1);
for (int j = left; j <= right - 1; j++)
{
numcompares++;
if (arr[j] < pivot)
{
k++;
swap(arr[k], arr[j]);
}
}
swap(arr[k + 1], arr[right]);
return (k + 1);
}
Any ideas as to what is going wrong in here? Thank you.

I have written a quick sort code and logic seem pretty correct but there is no output on the console

I have written a quick sort code and logic seem pretty correct but there is no output on the console.
when only index function runs the output is correct and also the output loop is correct but when quicSort function is added then there is no output.
#include <iostream>
using namespace std;
int index(int* a, int s, int e) {
int i, j, start, piv, temp;
start = s;
piv = a[e];
for (i = start; i <= e; i++) {
if (a[i] <= piv) {
temp = a[i];
a[i] = a[start];
a[start] = temp;
start++;
}
}
return start;
}
void quickSort(int* a, int s, int e) {
int pivot;
if (s < e) {
pivot = index(a, s, e);
quickSort(a, s, pivot - 1);
quickSort(a, pivot + 1, e);
}
}
int main() {
int A[] = {2, 5, 8, 3, 6, 9, 1, 4};
quickSort(A, 0, 7);
for (int i = 0; i < 8; i++) {
cout << A[i];
}
return 0;
}
the output should be sorted array
Code needs two fixes. Changes noted in comments:
#include <iostream>
using namespace std;
int index(int* a, int s, int e) {
int i, start, piv; // j, temp not used
start = s;
piv = a[e];
for (i = start; i <= e; i++) {
if (a[i] < piv) { // fix (not <=)
swap(a[i], a[start]); // simplify
start++;
}
}
swap(a[start], a[e]); // fix (swap pivot into place)
return start;
}
void quickSort(int* a, int s, int e) {
int pivot;
if (s < e) {
pivot = index(a, s, e);
quickSort(a, s, pivot - 1);
quickSort(a, pivot + 1, e);
}
}
int main() {
int A[] = {2, 5, 8, 3, 6, 9, 1, 4};
quickSort(A, 0, 7);
for (int i = 0; i < 8; i++) {
cout << A[i] << " "; // put space beteen numbers
}
cout << endl;
return 0;
}
I think you get confused by bubblesort when creating your quicksort program.
The quicksort ideia is to break the vector in smaller vectors one with the numbers bigger than the pivot e another with the numbers smaller than the pivot.
You should round up your code in C++ data structures like vectors.
One example is, with c++11:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
vector<int> quicksort(vector<int> data) {
if (data.size() == 1) return data;
vector<int> small_numbers;
vector<int> big_numbers;
vector<int> ret;
float pivot = accumulate(data.begin(), data.end(), 0.0) / data.size();
for (int value : data) {
if (value < pivot) {
small_numbers.push_back(value);
} else {
big_numbers.push_back(value);
}
}
if (small_numbers.empty()) return big_numbers;
small_numbers = quicksort(small_numbers);
big_numbers = quicksort(big_numbers);
ret.insert(ret.end(), small_numbers.begin(), small_numbers.end());
ret.insert(ret.end(), big_numbers.begin(), big_numbers.end());
return ret;
}
int main() {
vector<int> A({2, 5, 8, 3, 6, 9, 1, 4});
A = quicksort(A);
for (int value : A) cout << value << endl;
return 0;
}
This example break the the vector into two vectors, the pivot is the mean value of the values of vector. It calls the function recursively until it calls a vector with the size of 1 element.
Hope it push you to a less complicated way of see quicksort.

How to partition correctly using the median of the first, middle, and last elements?

My multiway_merge function is incorrect but not sure why. Seems to be correct logically but if the sorting is correct then it must be the merging. I am supposed to make a min heap of the first element of each sorted vector and then add them to the output_list in the correct sorted order and keep doing that until all the numbers have been added to the output_list.
int partition(vector<int>& list, int first, int last) {
// The pivot should be the median of the
// first, middle, and last elements.
int middle = first + (last - first) / 2;
if (list[first] > list[middle])
swap(list[first], list[middle]);
if (list[first] > list[last])
swap(list[first], list[last]);
if (list[middle] > list[last])
swap(list[middle], list[last]);
swap(list[middle], list[first]);
int pivot = list[first];
int i = first - 1;
int j = last + 1;
while(true) {
do {
i++;
} while(list[i] < pivot);
do {
j--;
} while(list[j] > pivot);
if(i >= j)
return j;
swap(list[i], list[j]);
}
}
void quicksort(vector<int>& list, int first, int last) {
if(first < last) {
int pivotLocation = partition(list, first, last);
quicksort(list, first, pivotLocation);
quicksort(list, pivotLocation + 1, last);
}
}
void multiway_merge(vector<vector<int> >& input_lists,
vector<int>& output_list) {
int numLists = (int) (input_lists.size());
int numElements = (int) (input_lists[0].size());
priority_queue<int, vector<int>, greater<int> > minHeap;
for(int i = 0; i < numLists; i++) {
for(int j = 0; j < numElements; j++) {
minHeap.push(input_lists[i][j]);
if (minHeap.size() > numLists) {
output_list.push_back(minHeap.top());
minHeap.pop();
}
}
}
while (minHeap.size()) {
output_list.push_back(minHeap.top());
minHeap.pop();
}
}
int main(int argc, char** argv) {
int n, m;
cin >> n >> m;
vector<vector<int> > input_lists(n, vector<int>(m));
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cin >> input_lists[i][j];
}
}
// Quicksort k sublists
for (int i = 0; i < input_lists.size(); ++i)
quicksort(input_lists[i], 0, m-1);
// Merge n input sublists into one sorted list
vector<int> output_list;
multiway_merge(input_lists, output_list);
for(int i = 0; i < output_list.size(); ++i)
cout << output_list[i] << " ";
cout << endl;
}
I couldn't find any logical error with your partition function, Maybe your problem source is in the way that you call this function from sort function and you didn't share that function with us so I had to guess.
Anyway, using your implementation of partition function the quick sort algorithm would be something like this :
#include <iostream>
#include <vector>
#include <algorithm>
int partition(std::vector<int> &vec, int low, int high)
{
int middle = low + (high - low) / 2;
if((vec.at(middle) >= vec.at(low) && vec.at(middle) <= vec.at(high))
|| (vec.at(middle) <= vec.at(low) && vec.at(middle) >= vec.at(high)))
std::swap(vec.at(high), vec.at(middle));
if((vec.at(high) >= vec.at(low) && vec.at(high) <= vec.at(middle))
|| (vec.at(high) <= vec.at(low) && vec.at(high) >= vec.at(middle)))
std::swap(vec.at(low), vec.at(high));
int pivot = vec.at(low);
int i = low - 1, j = high + 1;
while(true)
{
do
{
i++;
} while(vec.at(i) < pivot);
do
{
j--;
} while(vec.at(j) > pivot);
if(i >= j)
return j;
std::swap(vec.at(i), vec.at(j));
}
}
void quickSort(std::vector<int> &vec, int low, int high)
{
if(low < high)
{
int pi = partition(vec, low, high);
quickSort(vec, low, pi);
quickSort(vec, pi + 1, high);
}
}
int main()
{
std::vector<int> input = {10, 7, 15, 9, 1, 33};
quickSort(input, 0, input.size() - 1);
for(auto iter = input.begin(); iter != input.end(); ++iter)
std::cout << *iter << " ";
std::cout << "\n";
system("pause");
return 0;
}
EDIT : Your quick sort wasn't the source of the problem, You have problem merging sorted vectors, so the source of the problem is in logic of your multiway_merge function.
You used priority_queue to achieve this merge and it's a valid approach, but I think you miss understood how priority_queue actually works.
you can enqueue as many elements you want but the order of outgoing elements are determined by the way you set your priority. Take a loot at priority_queue.
Your compare condition to determine priority is right too, I mean using greater<int>. So the only problem in your code is one extra condition that you don't need it at all. I mean these lines of code :
if(minHeap.size() > numLists)
{
output_list.push_back(minHeap.top());
minHeap.pop();
}
Remove this condition and your multiway_merge will work fine. The final implementation of this function would be :
void multiway_merge(vector<vector<int> >& input_lists,
vector<int>& output_list)
{
unsigned int numLists = (int)(input_lists.size());
int numElements = (int)(input_lists[0].size());
priority_queue<int, vector<int>, greater<int> > minHeap;
for(int i = 0; i < numLists; i++)
{
for(int j = 0; j < numElements; j++)
{
minHeap.push(input_lists[i][j]);
}
}
while(minHeap.size())
{
output_list.push_back(minHeap.top());
minHeap.pop();
}
}

Is there any input for which selection sort outperforms bubble sort?

I mean like...partial, full or reverse sorted arrays.
I have already tried the following: random, fully sorted, almost sorted, partially sorted, rever sorted and the count of bubble is lesser when it's fully sorted. In all other cases, it's the same.
int selectionSort(int a[], int l, int r) {
int count = 0;
for (int i = l; i < r; i++) {
int min = i;
for (int j = i + 1; j <= r; j++) {
if (a[j] < a[min]) min = j;
count++;
}
if (i != min) swap(a[i], a[min]);
}
return count;
}
int bubbleSort(int a[], int l, int r) {
int count = 0;
bool flag = false;
for (int i = l; i < r; i++) {
for (int j = r; j > i; j--) {
if (a[j-1] > a[j]) {
if (flag == false) flag = true;
swap(a[j - 1], a[j]);
}
count++;
}
if (flag == false) break;
}
return count;
}
The count returns the number of comparisons BTW.
Among simple average-case Θ(n2) algorithms, selection sort almost always outperforms bubble sort.
Source: Wikipedia
I hinted at this already in comments, but here's some updated code for you that counts both comparisons and exchanges/swaps, and illustrates that for some random input the number of exchanges/swaps is where selection sort outperforms bubble sort.
#include <iostream>
#include <vector>
#include <utility>
#include <cassert>
using namespace std;
struct Stats { int swaps_ = 0, compares_ = 0; };
std::ostream& operator<<(std::ostream& os, const Stats& s)
{
return os << "{ swaps " << s.swaps_
<< ", compares " << s.compares_ << " }";
}
Stats selectionSort(std::vector<int>& a, int l, int r) {
Stats stats;
for (int i = l; i < r; i++) {
int min = i;
for (int j = i + 1; j <= r; j++) {
if (a.at(j) < a.at(min)) min = j;
++stats.compares_;
}
if (i != min) {
swap(a.at(i), a.at(min));
++stats.swaps_;
}
}
return stats;
}
Stats bubbleSort(std::vector<int>& a, int l, int r) {
Stats stats;
bool flag = false;
for (int i = l; i < r; i++) {
for (int j = r; j > i; j--) {
if (a.at(j-1) > a.at(j)) {
if (flag == false) flag = true;
swap(a.at(j - 1), a.at(j));
++stats.swaps_;
}
++stats.compares_;
}
if (flag == false) break;
}
return stats;
}
int main()
{
std::vector<int> v1{ 4, 8, 3, 8, 10, -1, 3, 20, 5 };
std::vector<int> v1s = v1;
std::cout << "sel " << selectionSort(v1s, 0, v1s.size() - 1);
std::vector<int> v1b = v1;
std::cout << ", bub " << bubbleSort(v1b, 0, v1b.size() - 1) << '\n';
assert(v1s == v1b);
// always a good idea to check the code's doing what you expect...
for (int i : v1s) std::cout << i << ' ';
std::cout << '\n';
}
Output:
sel { swaps 6, compares 36 }, bub { swaps 15, compares 36 }
-1 3 3 4 5 8 8 10 20
You can observe / copy / fork-and-edit / run the code online here.

How to sort without using loop

How do I sort an array without using a loop in C++? I think it might use recursion, but I do not know how to implement it.
Use std::sort defined in algorithm header file
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int a[]={5,3,4,1,2};
sort(a,a+5);
for(int i=0;i<5;i++)
cout<<a[i]<<" "; // 1 2 3 4 5
return 0;
}
//C++
void bubblesort(vector<int> &arr, int iteration) {
if(iteration == 0)
return;
bubbleswap(arr, 0, 1, iteration);
bubblesort(arr, iteration-1);
}
void bubbleswap(vector<int> &arr, int i, int j, int n) {
if(j>=n)
return ;
if(arr[i] < arr[j]){
swap(arr[i], arr[j]);
}
bubbleswap(arr, i+1, j+1, n);
}
void sort(vector<int> &arr) {
int n = arr.size();
if(n<=1)
return ;
bubblesort(arr, n);
}
Recursive Selection Sort
#include <iostream>
#include <vector>
using namespace std;
//----------------------------------------------------------
int recursive_min(vector<int>& a, size_t first) {
//base case
if (first + 1 >= a.size()) {
return first;
}
else {
size_t min_index {first};
int temp_index {recursive_min(a, first + 1)};
if (a[min_index] > a[temp_index]) {
min_index = temp_index;
}
return min_index;
}
}
//----------------------------------------------------------
void selectionSort(vector<int>& a, size_t step = 0) {
//base case
if (step + 1 >= a.size()) {
return;
}
else {
int temp_index {recursive_min(a, step + 1)};
if (a[step] > a[temp_index]) {
swap(a[step], a[temp_index]);
}
selectionSort(a, step + 1);
}
}
//---------------------------------------------------------
int main() {
vector<int> vec {11, 23, 2, 50, 3, 8, 1, 4, 5};
selectionSort(vec);
for (int i : vec) {
cout << i << " ";
}
}
Recursive Insertion Sort
#include <iostream>
#include <vector>
using namespace std;
int recursive_insert(vector<int>& a, int key, int i) {
//base case
if (i <= -1 || a[i] <= key) {
return i;
}
else {
a[i + 1] = a[i];
return recursive_insert(a, key, i - 1);
}
}
//-----------------------------------------------------------------------------
void insertion_sort(vector<int>& a, size_t j = 1) {
//base case
if (j >= a.size()) {
return;
}
else {
int key = a[j];
int i = recursive_insert(a, a[j], j - 1);
a[i + 1] = key;
insertion_sort(a, j + 1);
}
}
//-----------------------------------------------------------------------------
int main() {
vector<int> vec {11, 23, 2, 50, 3, 8, 1, 4, 5};
insertion_sort(vec);
for (int i : vec) {
cout << i << " ";
}
}
#include<stdio.h>
int * sort(int *p,int i,int j,int size)
{
if(i<size)
{
if(j<size-i-1)
{
if(p[j]>p[j+1])
{
int temp = p[j];
p[j] = p[j+1];
p[j+1] = temp;
}
}
else
{
j=-1;
++i;
}
p = sort(p,i,++j,size);
}
return p;
}
Below is how to use it
int main()
{
int array[] ={1,5,2,7,3};
int len = sizeof(array)/sizeof(int);
int *a = sort(array,0,0,len);
for(int i=0;i<len;i++)
{
printf("\n array[%d]->%d",i,a[i]);
}
}
I think you are looking for the Quicksort Algorithm
There are more ways to sort an array.
If you are trying to implement a loop recursively, you can check out a wikipedia article. It is well explained under "Recursion computer science".
Otherwise you can try to implement different sorting algorithms. The well known are Quicksort and Mergesort.
There are many sorting algorithms
Well, I'm writing a Python interpreter and didn't write loop yet. I got the codebase from some website and rewrite the loop by some recursion. It works. :D
def quickSort(arr, low, high):
def jLoop(low, high, pivot, i, j):
if j >= high:
temp = arr[high]
arr[high] = arr[i+1]
arr[i+1] = temp
return (i+1)
else:
if arr[j] <= pivot:
i = i+1
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
return jLoop(low, high, pivot, i, j+1)
def partition(low, high):
i = (low - 1)
pivot = arr[high]
return jLoop(low, high, pivot, i, low)
def quick(low, high):
if low < high:
pi = partition(low, high)
quick(low, pi-1)
quick(pi+1, high)
quick(low, high)
return arr
my_list = [0, 6, 3, 1, 2, 4, 7, 5]
length = 8
print quickSort(my_list, 0, 7)
my_list = [9, 0, 8, 1, 7, 2, 6, 3, 5, 4]
length = 10
print quickSort(my_list, 0, 9)