Could someone please help me and tell me why quick sort algorithm will not sort the final element?
When I input:
6 89 2 78 12 19 99 43 7 63
I get an ALMOST sorted:
2 6 7 12 78 19 43 99 63 89
I have tried to figure this out my self, but when I work my way thought the code at some point I get lost doing a desk check.
#include <iostream>
using namespace std;
// function prototypes
void quickSort(int arrayList[], int left, int right);
int choosePivot(int arrayList[], int listSize);
int partition(int array[], int left, int right);
void printArray(int theArray[], int Size);
// void swap(int value1, int value2);
int main()
{
int myList[] = {6, 89, 2, 78, 12, 19, 99, 43, 7, 63};
printArray(myList, 10);
quickSort(myList, 0, 9);
printArray(myList, 10);
//int myList2[] = { 7, 4, 9, 10, -9 };
//printArray(myList2, 5);
//quickSort(myList2, 0, 5);
//printArray(myList2, 5);
cin;
getchar;
getchar;
return 0;
}
void quickSort(int arrayList[], int left, int right)
{
//if (left < right)
if(right > left)
{
int p = partition(arrayList, left, right);
printArray(arrayList, 10);
quickSort(arrayList, left, p-1);
quickSort(arrayList, p + 1, right);
}
}
// left (index value) - left most part of the array we are working on
// right (index value) - right most part of the array we are working on
int partition(int array[], int left, int right)
{
//int pivot = array[left]; // I will have to write a function to find the
// optimum pivot point, this is the naive solution
int pivot = array[(left+right)/2];
int i = left;
int j = right;
int temp;
while (i < j)
{
//cout << "in the loop" ;
while (array[i] < pivot)
i++;
while (array[j] > pivot)
j--;
if (i < j)
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
i++;
j--;
}
}
return i;
}
void printArray(int theArray[], int Size)
{
for (int i = 0; i < Size; i++)
{
cout << theArray[i] << " ";
}
cout << endl ;
}
You have a bug in your partition() function (I take it that it's Hoare partition algorithm implementation). You just need to remove this code:
i++;
j--;
after swapping values.
Here is the corrected partition() function code:
int partition(int array[], int left, int right)
{
int pivot = array[(left + right) / 2];
int i = left;
int j = right;
while (i < j) {
while (array[i] < pivot)
i++;
while (array[j] > pivot)
j--;
if (i < j) {
int temp;
/* Swap array[i] and array[j] */
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
return i;
}
Even with this bug fixed, you should create a good unit test for your quicksort implementation, because there may be some other subtle bugs (it's very hard to write bug-less implementation of partition() from scratch). Check for edge cases, corner cases and boundary cases in your unit test.
I'm not sure how much this would help but when you get your pivot of
(left + right) / 2
you are doing (0+9) / 2 which is 4. But the thing is, the middle should be 5 if the size of the array is 10.
Related
Hello i got an array of 10 elements. [0...9].
Inside of it there are numbers - [0,1,2,...,8,9].
I'm trying to sort the array descending but instead of [9,8,...,2,1] i am getting [ 4 3 2 1 0 5 6 7 8 9 ].
My quicksort code.
void q_n(int arr[], int left, int right) {
int i = left, j = right;
int tmp;
int pivot = arr[(left + right) / 2];
/* partition */
while (i <= j) {
while (arr[i] > pivot)
i++;
while (arr[j] < pivot)
j--;
if (i <= j) {
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
}
};
/* recursion */
if (left < j)
q_n(arr, left, j);
if (i < right)
q_n(arr, i, right);
}
Anyone can help me with this ? ;s
i found the problem. So stupid. Dont know why this happened.
The problem was not in the qsort code but in the calling function.
q_n(array, 0, sizeof(int));
changed to:
q_n(array, 0, 9);
and worked perfectly.
If you don't have to implement quick sort, use the built in one:
qsort(A, n, sizeof(int), compare_function);
where A is an array of int, n is the number of elements in the array and you have to specify a compare function:
int compare_function(const void *ptr1, const void *ptr2)
{
int tptr1 = *(int*)ptr1;
int tptr2 = *(int*)ptr2;
return tptr2 - tptr1;
}
use return tptr1 - tptr2; for ascending order and return tptr2 - tptr1; for descending
EDIT:
I just copy-pasted the previous code and didn't noticed the int-float mistake. Here is a complete example how qsort works for those who want to use it:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int compare_function(const void *a, const void *b)
{
return *(int*)a - *(int*)b; //ascending
//return *(int*)b - *(int*)a; //descending
}
int main()
{
int A[100];
srand(time(NULL));
for(int i=0; i<100; ++i)
{
A[i] = rand();
}
qsort(A, 100, sizeof(int), compare_function);
for(int i=0; i<100; ++i)
{
printf("%d\n", A[i]);
}
return 0;
}
I'm relatively new to C++/Algorithms, and I'm not quite sure what's wrong with my heapSort function. Given the numbers (6, 2, 9, 1, 5), I am outputting the following incorrect numbers:
9
4197040
2
4196422
6
Thanks for looking.
#include <iostream>
using namespace std;
void heapSort(int arr [], int size);
void reheapDown(int arr[], int root, int bottom);
void swap(int & num1, int & num2);
int main()
{
int arr[5] = {6, 2, 9, 1, 5};
heapSort(arr, 5);
for (int i = 0; i < 5; i++)
cout << arr[i] << endl;
return 0;
}
void heapSort(int arr [], int size){
int i;
for (i = size/2 -1; i >= 0; i--)
reheapDown(arr, i, size-1);
for (i = size - 1; i >= 1; i--){
swap(arr[0], arr[i]);
reheapDown(arr, 0, i-1);
}
}
void reheapDown(int arr[], int root, int bottom){
int max, right, left;
left = root * 2 + 1;
right = root * 2 + 2;
if (left <= bottom)
max = left;
else{
if (arr[left] <= right)
max = right;
else
max = left;
}
if (arr[root] < arr[max]){
swap(arr[root], arr[max]);
reheapDown(arr, max, bottom);
}
}
void swap(int & num1, int & num2){
int temp;
temp = num1;
num1 = num2;
num2 = temp;
}
At least one problem is that you are accessing out of bounds:
void reheapDown(int arr[], int root, int bottom){
int max = 0;
int left = root * 2 + 1;
int right = root * 2 + 2;
if (left <= bottom)
max = left;
else{
if (left < 0){
throw std::runtime_error("Uh oh, left is less than zero");
}
if (left > 4){
throw std::runtime_error("Uh oh, left is greater than 4");
}
if (arr[left] <= right)
max = right;
else
max = left;
}
if (arr[root] < arr[max]){
if (root < 0){
throw std::runtime_error("Uh oh, root is less than zero");
}
if (root > 4){
throw std::runtime_error("Uh oh, root is greater than 4");
}
if (root < 0 || root > 4){
throw std::runtime_error("Uh oh");
}
swap(arr[root], arr[max]);
reheapDown(arr, max, bottom);
}
}
Will output:
terminate called after throwing an instance of 'std::runtime_error'
what(): Uh oh, left is greater than 4
I'm trying to implement quick sort and figuring out the handling part for worst case of it. When pivot choose largest or lowest of element in the array, I got stuck in the middle of my algorithm and have no idea how to handle it.
#include <iostream>
void swap(int item1, int item2)
{
int temp = item1;
item1 = item2;
item2 = temp;
}
int partition(int array[], unsigned int left, unsigned int right)
{
int pivot = array[left];
int pivot_index = left;
for(++left, right; left <= right;)
{
if(array[left] >= pivot && array[right] < pivot)
swap(array[left], array[right]);
if(array[left] < pivot)
left++;
if(array[right] >= pivot)
right++;
}
swap(array[right], pivot_index);
return right;
}
void quicksort(int array[], unsigned int left, unsigned int right)
{
if(left < right)
{
int index = partition(array, left, right);
quicksort(array, 0, index - 1);
quicksort(array, index + 1, right);
}
}
int main()
{
int unsortedarray[] = {10, 0, 9, 3, 4, 5, 8, 1};
int length = sizeof(unsortedarray) / sizeof(int);
quicksort(unsortedarray, 0, length - 1);
for(unsigned int index = 0; index < static_cast<unsigned int>(length); ++index)
std::cout << unsortedarray[index] << std::endl;
return 0;
}
Your swap is working with local copies of the values to be swapped; it isn't making any changes to the arguments.
I don't understand why they give me different output when I compile them. For example ... when I compile only one algorithm the answer is good, the same is for the other one, but when I compile them both at the same time they give me some weird output.
My code:
#include <iostream>
using namespace std;
int parent(int i){
return i/2;
}
int leftChild(int i){
return 2*i+1;
}
int rightChild(int i){
return 2*i+2;
}
void maxHeapify(int a[], int i, int n){
int largest;
int temp;
int l = leftChild(i);
int r = rightChild(i);
// p.countOperation("CMPbottomUp",n);
if (l <= n && (a[l] > a[i]))
largest = l;
else
largest = i;
// p.countOperation("CMPbottomUp",n);
if (r <= n && (a[r] > a[largest]))
largest = r;
if (largest != i){
// p.countOperation("ATTbottomUp",n);
temp = a[i];
// p.countOperation("ATTbottomUp",n);
a[i] = a[largest];
//p.countOperation("ATTbottomUp",n);
a[largest] = temp;
maxHeapify(a, largest, n);
}
}
void buildMaxHeap(int a[], int n){
for (int i=n/2; i>=0; i--){
maxHeapify(a, i, n);
}
}
void heapSort(int a[],int n){
buildMaxHeap(a,n);
int n1=n;
int temp;
for(int i=n1;i>0;i--){
temp = a[0];
a[0] = a[i];
a[i] = temp;
n1--;
maxHeapify(a,0,n1);
}
}
int partitionArray(int arr[], int left, int right){
int i = left, j = right;
int tmp;
int pivot = arr[(left + right) / 2];
while (i <= j) {
while (arr[i] < pivot)
i++;
while (arr[j] > pivot)
j--;
if (i <= j) {
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
}
}
return i;
}
void quickSort(int arr[], int left, int right) {
int index;
index = partitionArray(arr, left, right);
if (left < index - 1)
quickSort(arr, left, index - 1);
if (index < right)
quickSort(arr, index, right);
}
int main(){
int x[8]= {5,87,21,4,12,7,44,3};
int a[8];
for(int i=0;i<8;i++){
a[i] = x[i];
}
heapSort(x,8);
quickSort(a,0,8);
for(int i=0;i<8;i++){
cout<<a[i]<<' ';
}
cout<<endl;
for(int j=0;j<8;j++){
cout<<x[j]<<' ';
}
return 0;
}
Example output:
1) When I compile only one algorithm the output is : 3,4,5,7,12,21,44,87 (which is good)
2) When I compile both of them in the code the output is: 87,4,5,7,12,21,44,87 (quickSort) and 3,3,4,5,7,12,21,44 (heapSort)
I think that should work:
heapSort(x,7);
quickSort(a,0,7);
Arrays a and x are right next to each others in stack. Seeing how you have duplicate value 87 in output, it seems your sort functions access memory outside the array you give to them. This is buffer overrun, a type of Undefined Behaviour. With that, your code could do anything because you have corrupted variable values (or worse, corrupted addresses/pointers).
Double check how you access arrays. Remember that C array indexes for your arrays of length 8 are 0..7!
I'm not looking to copy a qsort algorithm. I'm practicing writing qsort and this is what I've come up with and I'm interested in what part of my code is wrong. Please don't tell me that this is homework cause I could just use the code in the link below.
Reference: http://xoax.net/comp/sci/algorithms/Lesson4.php
When this runs I get this in the console:
Program loaded.
run
[Switching to process 10738]
Running…
Current language: auto; currently c++
Program received signal: “EXC_ARITHMETIC”.
void myQSort(int min, int max, int* myArray)
{
// Initially find a random pivot
int pivotIndex = rand() % max;
int pivot = myArray[pivotIndex];
int i = 0 , j = max-1;
// Pointer to begining of array and one to the end
int* begin = myArray;
int* end = &myArray[max-1];
// While begin < end
while( begin < end )
{
// Find the lowest bound number to swap
while( *begin < pivot )
{
begin++;
}
while( *end > pivot )
{
// Find the highest bound number to swap
end--;
}
// Do the swap
swap(begin,end);
}
// Partition left
myQSort(0, pivotIndex-1, myArray);
// Partiion right
myQSort(pivotIndex+1,max, myArray);
}
EDIT--
Code for Swap:
void swap(int* num, int* num2)
{
int temp = *num;
*num = *num2;
*num2 = temp;
}
// sort interval [begin, end)
void myQSort(int* begin, int* end)
{
if(end - begin < 2)
return;
int* l = begin;
int* r = end - 1;
// Initially find a random pivot
int* pivot = l + rand() % (r - l + 1);
while(l != r)
{
// Find the lowest bound number to swap
while(*l < *pivot) ++l;
while(*r >= *pivot && l < r) --r;
// Do the swap
if(pivot == l) { pivot = r; }
std::swap(*l, *r);
}
// Here l == r and numbers in the interval [begin, r) are lower and in the interval [l, end) are greater or equal than the pivot
// Move pivot to the position
std::swap(*pivot, *l);
// Sort left
myQSort(begin, l);
// Sort right
myQSort(l + 1, end);
}
You're not using the min parameter in your code, anywhere. You need to set begin and your pivot value using that.
I tried working out the codes above. But, they don't compile.
#Mihran: Your solution is correct algorithmically but the following line generates an error:
myQSort(min, begin - myArray, myArray);
This is because begin is of type int* and myArray is of type long, following which the compiler shows this error message:
implicit conversion loses integer precision
Here's a working solution in C++:
#include <iostream>
using namespace std;
void mySwap(int& num1, int& num2){
int temp = num1;
num1 = num2;
num2 = temp;
}
void myQsort(int myArray[], int min, int max){
int pivot = myArray[(min + max) / 2];
int left = min, right = max;
while (left < right) {
while (myArray[left] < pivot) {
left++;
}
while (myArray[right] > pivot) {
right--;
}
if (left <= right) {
mySwap(myArray[left], myArray[right]);
left++;
right--;
}
}
if (min < right) {
myQsort(myArray, min, right);
}
if (left < max) {
myQsort(myArray, left, max);
}
}
int main()
{
int myArray[] = {1, 12, -5, 260, 7, 14, 3, 7, 2};
int min = 0;
int max = sizeof(myArray) / sizeof(int);
myQsort(myArray, min, max-1);
for (int i = 0; i < max; i++) {
cout<<myArray[i]<<" ";
}
return 0;
}
Here's a clear C++ implementation, for reference:
#include <iostream>
#include <vector>
using namespace std;
int partition(std::vector<int>& arr, int low, int high) {
// set wall index
int wall_index = low;
int curr_index = low;
int pivot_elem = arr[high]; // taking last element as pivot_element
// loop through the entire received arr
for (int i = curr_index; i < high; ++i) {
// if element is less than or equal to pivot_elem
// swap the element with element on the right of the wall
// i.e swap arr[i] with arr[wall_index]
if (arr[i] <= pivot_elem) {
// swap
int temp = arr[wall_index];
arr[wall_index] = arr[i];
arr[i] = temp;
// move the wall one index to the right
wall_index++;
curr_index++;
} else {
// if the element is greater than the pivot_element
// then keep the wall at the same point and do nothing
curr_index++;
}
}
// need to swap the pivot_elem i.e arr[high] with the element right of the wall
int temp = arr[wall_index];
arr[wall_index] = arr[high];
arr[high] = temp;
return wall_index;
}
void quick_sort(std::vector<int>& arr, int low, int high) {
if (low < high) { // element with single arr always have low >= high
int split = partition(arr, low, high);
quick_sort(arr, low, split-1);
quick_sort(arr, split, high);
}
}
int main() {
std::vector<int> data = {6,13,8,4,2,7,16,3,8};
int N = data.size();
quick_sort(data, 0, N-1);
for (int i : data) {
cout << i << " ";
}
return 0;
}
I don't see a clean implementation of Quicksort on SO, so here is my easy to understand implementation
PLEASE DONT USE IN PRODUCTION CODE
This is only for your understanding
// Swap position a with b in an array of integer numbers
void swap(int *numbers, int a, int b){
int temp = numbers[a];
numbers[a] = numbers[b];
numbers[b] = temp;
}
static int partition(int *data, int low, int high) {
int left = low, right = high, pivot = data[low];
while (left < right) {
// Everthing on the left of pivot is lower than the pivot
while ((left <= right) && data[left] <= pivot) // <= is because left is the pivot initially
left++;
// Everything on the right of the pivot is greater than the pivot
while((left <= right) && data[right] > pivot)
right--;
if (left < right)
swap(data, left, right);
}
// Put the pivot in the 'rigthful' place
swap(data, low, right);
return right;
}
// Quicksort
static void quick_sort(int *numbers, int low, int high)
{
if (high > low) {
int p_index = partition(numbers, low, high);
quick_sort(numbers, low , p_index - 1);
quick_sort(numbers, p_index + 1, high);
}
}