elem_t select(elem_t* list, size_t begin, size_t end, size_t pos) { if (begin == end) { return list[begin]; } size_t pivot = select_pivot(list, begin, end); size_t new_pivot = partition(list, begin, end, pivot); if (begin + pos == new_pivot) return list[new_pivot]; else if (begin + pos < new_pivot) return select(list, begin, new_pivot - 1, pos); else return select(list, new_pivot + 1, end, pos - new_pivot - 1); }
void quick_sort(int *a, int left, int right) { int pivotIndex; int storeIndex; if (left < right) { pivotIndex = select_pivot(a, left, right); storeIndex = partition(a, left, right, pivotIndex); quick_sort(a, left, storeIndex - 1); quick_sort(a, storeIndex + 1, right); } }
/* return values: 0 == successful, 1 == error */ static int qsort_decreasing( struct cell v[], int left, int right ) { int pivot; int llen, rlen; int lleft, lright, rleft, rright; if ( pushstack( left )) return 1; if ( pushstack( right )) return 2; while ( stack_pointer != stack ) { if (popstack(&right)) return 3; if (popstack(&left )) return 4; if ( right - left > 0 ) { pivot = select_pivot( v, left, right ); partition_dec( v, &llen, &rlen, &lleft, &lright, &rleft, &rright, pivot, left, right ); if ( llen > rlen ) { if ( pushstack( lleft )) return 5; if ( pushstack( lright )) return 6; if ( pushstack( rleft )) return 7; if ( pushstack( rright )) return 8; } else{ if ( pushstack( rleft )) return 9; if ( pushstack( rright )) return 10; if ( pushstack( lleft )) return 11; if ( pushstack( lright )) return 12; } } } return 0; }
int* quicksort(int* array, int length) { if((length < 2) || (length == 2 && array[0] == array[1])){ return array; } int* __greater = (int*) malloc(length * sizeof(int)); int* __less = (int*) malloc(length * sizeof(int)); int i = 0, greater_length = 0, less_length = 0; int pivot = select_pivot(array, length); for(; i < length; i++) { if(array[i] < pivot) { __less[less_length] = array[i]; less_length ++; } else { __greater[greater_length] = array[i]; greater_length ++; } } int* greater = copy_array(__greater, greater_length); int* less = copy_array(__less, less_length); free(__greater); free(__less); int* less_sorted = quicksort(less, less_length); int* greater_sorted = quicksort(greater, greater_length); int* merged = merge(less_sorted, less_length, greater_sorted, greater_length); free(greater_sorted); free(less_sorted); return merged; }
/***************************************************** * Thread function that will attempt to sort locally */ void *parallel_qsort(void *arg_struct) { int st_idx, en_idx, rc; double median = 0; struct thread_data index_left, index_right; void *status; pthread_t first_thread; pthread_t second_thread; /* * Extract the thread args from the structure passed in */ struct thread_data *args; args = (struct thread_data *) arg_struct; st_idx = args->st_idx; en_idx = args->en_idx; if (en_idx > st_idx) { int N = en_idx - st_idx + 1; // Get number of // elements in // this array if (floor_log2(thread_count) < MAXDEPTH && N > floor_log2(MAXLEN)) { // If /* * 1. Pivot Selection Strategy */ median = select_pivot(st_idx, en_idx); // printf("Median chosen ---> %ld\n", median); /* * 2. Partition the data into subarrays lesser and greater * than pivot */ int pivot_index = partition_new(st_idx, en_idx, median); // partition_new( /* * Update the thread counter */ pthread_mutex_lock(&mutexthread); /* Lock Mutex */ thread_count += 2; ++real_thread_count; pthread_mutex_unlock(&mutexthread); /* Unlock Mutex */ /* * Fire the thread to sort the lesser than sub-array */ index_left.st_idx = st_idx; index_left.en_idx = pivot_index - 1; /* * Re-use current thread to sort the greater array ... so no * new thread creation */ index_right.st_idx = pivot_index + 1; index_right.en_idx = en_idx; // printf("****** Parallel Sorting now (%d,%d) and (%d,%d) N = // %d depth = %d\n", st_idx, pivot_index - 1, pivot_index + 1, // en_idx, N, floor_log2( thread_count ) ); /* * Now we have called a new thread to sort the lesser array */ rc = pthread_create(&first_thread, NULL, parallel_qsort, (void *) &index_left); rc = pthread_create(&second_thread, NULL, parallel_qsort, (void *) &index_right); pthread_join(first_thread, NULL); pthread_join(second_thread, NULL); } else { // printf("****** Serial Sorting now (%d,%d) N = %d depth = // %d\n", st_idx, en_idx, N, floor_log2( thread_count ) ); serial_quickSort(st_idx, en_idx); // Sort Serially the list } /* * void *pquick(void *arg){ ... pthread_t leftthr,rightthr; ... * * if (right > left){ if (recursionlev<MAXLEVELS) { ... * pthread_create(&leftthr, NULL, pquick, (void *) &leftarg); * pthread_create(&rightthr, NULL, pquick, (void *) &rightarg); * pthread_join(leftthr, NULL); pthread_join(rightthr, NULL); } * else { quicksort(left); // Serial quicksort quicksort(right); } * * } } */ } // End of main if /* * And... EXIT */ pthread_exit(NULL); }
static void test_select_pivot_short_array(){ int array[2] = {6,5}; int pivot = select_pivot(array, 2); assert(contains_element(pivot, array, 2)); }
static void test_select_pivot_long_array(){ int array[10] = {6,5,1,9,4,7,5,12,8,4}; int pivot = select_pivot(array, 10); assert(contains_element(pivot, array, 10)); }