Getting segmentation fault while implementing quick sort - c

I want to implement heap sort. For the purpose, I went through this http://faculty.simpson.edu/lydia.sinapova/www/cmsc250/LN250_Tremblay/L06-QuickSort.htm#basic tutorial and wrote the following code:
#include <stdio.h>
int quick_sort(int a[],int first,int last);
int main()
{
int a[]= {12,3,4,23,1,7,9,34,89,45};
int i;
printf("Enter 10 integers: \n");
for ( i = 0 ; i < 10 ; i++ )
{
scanf("%d",&a[i]);
printf("\t%d\n",a[i]);
}
for ( i = 0 ; i < 10 ; i++ )
{
printf("\n%d ",a[i]);
}
quick_sort(a,0,9);
for ( i = 0 ; i < 10 ; i++ )
{
printf("%d ",a[i]);
}
return 0;
}
int quick_sort(int a[],int first,int last)
{
int i,j,pivot,temp ;
if ( first - last <= 1 && first - last >= -1 )
{
return 0;
}
else
{
i = first ;
j = last ;
pivot = a[(i+j) / 2 ] ;
while ( i != j )
{
while ( a[i] < pivot )
{
i++;
}
while( a[j] > pivot )
{
j--;
}
temp = a[i] ;
a[i] = a[j] ;
a[j] = temp ;
}
}
quick_sort(a,0,i-1);
quick_sort(a,j+1,9);
return 0;
}
While running it using gcc compiler I am getting segmentation fault. Please help me to solve it.

There are several thing that in the question's quick_sort() function that are a mystery to me. Not that they are wrong; it's just that the purpose of various manipulations escapes me.
After working on it for a while, here is my version:
void quick_sort(int *a, int first, int last)
{
int i,j,pivot,temp;
if(last <= 1)
return;
pivot = a[first + last/2];
j = first + last/2;
temp = a[first];
a[first] = a[j];
a[j] = temp;
j = first;
for(i = first+1; i < first+last; i++)
{
if(a[i] < pivot)
{
j++;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
temp = a[first];
a[first] = a[j];
a[j] = temp;
quick_sort(a, first, j-first);
quick_sort(a, j+1, first+last-j-1);
return;
}
Working spoiler testcase here.

I'd try:
quick_sort(a,first,i-1);
quick_sort(a,j+1,last);
Instead of:
quick_sort(a,0,i-1);
quick_sort(a,j+1,9);
It at least allows the sort to work for lists different than 10 values....
You also need to check if i != j after every change, so I think that's problematic in your code as well. Or at least use i than j and the while would NEVER end.

Related

GOTO command in C

I've tried to sort 5 integers array using GOTO (using in for the first time) and if statement only,
but I've debugged this code and I couldn't figure why that's not working, I don't fully understant how to use the GOTO and why I've got stuck inside the swapp loop, any help ?
int* sort5integersIFGOTO(int* arr)
{
int i = 0, j = 1;
start:
if (arr[i] > arr[j])
goto swapp;
swapp:
swap(&arr[i], &arr[j]);
if (j < 4)
{
j++;
goto start;
}
if (i < 3)
{
i++;
j = i+1;
goto start;
}
return arr;
}
This piece of code:
if (arr[i] > arr[j])
goto swapp;
swapp:
swap(&arr[i], &arr[j]);
alwayds does the same thing -- if the test is true, it jumps to the label (on the very next line) and if the test is false, it falls through to the label. So the result of the comparison is irrelevant, and it always swaps. You probably want
if (arr[i] > arr[j])
swap(&arr[i], &arr[j]);
with no label or goto here at all...
For starters try always to write more general functions that for example can sort arrays of various sizes.
Also the return type int * of the function sort5integersIFGOTO does not make a great sense. Usually such functions have the return type void.
Your function is incorrect. For example if arr[i] is not greater than arr[j] nevertheless the control is passed to the statement under the label swapp that follows the if statement and in any case two elements of the array are swapped.
start:
if (arr[i] > arr[j])
goto swapp;
swapp:
swap(&arr[i], &arr[j]);
Also within the function there are used unclear magic numbers as 3 and 4 though the passed array as it follows from the description has 5 elements.
The function can be defined the following way as it is shown in the demonstration program below.
#include <stdio.h>
void swap( int *a, int *b )
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void sort5integersIFGOTO( int *arr, size_t n )
{
size_t i = 0;
start:
if ( i < n )
{
size_t j = i;
next:
if ( ++j < n )
{
if ( arr[j] < arr[i] )
{
swap( arr + i, arr + j );
}
goto next;
}
else
{
++i;
goto start;
}
}
}
int main(void)
{
int arr[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
const size_t N = sizeof( arr ) / sizeof( *arr );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", arr[i] );
}
putchar( '\n' );
sort5integersIFGOTO( arr, N );
for ( size_t i = 0; i < N; i++ )
{
printf( "%d ", arr[i] );
}
putchar( '\n' );
}
The program output is
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
As you can see neither magic number is used within the function. The function can sort arrays of various sizes.
It is not difficult to rewrite the function using for loops instead of goto statements. For example
void sort5integersIFGOTO( int *arr, size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = i; ++j < n; )
{
if ( arr[j] < arr[i] )
{
swap( arr + i, arr + j );
}
}
}
}

Counting Comparisions in Quicksort: Wrong answer

I have written code to compute the number of comparisons done in QuickSort.
The algorithm increases the count of comparisons by m-1 whenever a quicksort is performed on an array of length m (Since pivot will be compared with everything other than itself).
The choice of the pivot is always the first element of the array.
When I try to use it on an array of 10000 entries, it is giving me a wrong answer.
A correct answer is supposed to be 162085.
The link to the dataset is given below:
https://drive.google.com/file/d/0B0D_kFnzj_RrYm9NT0lrM3JfN2c/view?usp=sharing
The total comparisons are stored in x.
#include<stdio.h>
long long x=0;
int size=10000;
int A[10000];
int B[10000];
void quicksort(int A[],int begin,int end)
{
if(begin<end){
int i=begin;
int j=end;
int k;
int pivot=begin;
for(k=begin+1;k<=end;k++)
{
if(A[k]>A[pivot])
{
x++;
B[j]=A[k];
j--;
}
else
{
x++;
B[i]=A[k];
i++;
}
}
B[i]=A[pivot];
for(k=begin;k<=end;k++)
{
A[k]=B[k];
}
quicksort(A,begin,i-1);
quicksort(A,i+1,end);
}
else
{
if((end-begin)==1) x++;
}
}
int main()
{
FILE *myFile;
myFile = fopen("QuickSort.txt", "r");
int i;
for (i = 0; i < 10000; i++)
{
fscanf(myFile, "%d", &A[i]);
}
quicksort(A,0,size-1);
for(i=0;i<size;i++)
{
printf("%d\n",A[i]);
}
printf("%lld",x);
}
this part is wrong:
for(k=begin+1;k<=end;k++)
{
if(A[k]>A[pivot])
{
x++;
B[j]=A[k];
j--;
}
else
{
x++;
B[i]=A[k];
i++;
}
}
you don't have to go from begin till end. you only should go from begin till i>j.
see link: https://en.wikipedia.org/wiki/Quicksort
there the interesting lines are:
do
i := i + 1
while A[i] < pivot
do
j := j – 1
while A[j] > pivot
if i >= j then
return j
swap A[i] with A[j]
c / c++
i = begin;
j = end;
while(true)
{
while(i< end && A[i] < A[pivot])
{
i++;
}
while(j> begin && A[j] >= A[pivot])
{
j--;
}
if(i<j)
{
int temp = A[i]; //std::swap(A[i],A[j]);
A[i] = A[j];
A[j] = temp;
else
{
break;
}
}
In this code I don't use B because quicksort is an "inplace" algorithm and because of that we don't need to save the result into a different array

Removing duplicate entry from an array using hashmap

int main(array<System::String ^> ^args)
{
int arr[]={1,2,3,2,9,8,1,2,3,9};
int a[9];
int size = sizeof(arr)/sizeof(arr[0]);
int str[256]= {'\0'};
int i = 0;
for(i ; i < size ; i++)
{
if(str[arr[i]] == 0 )
str[arr[i]]= 1;
}
for( i = 0 ; i < size ; i++)
{
if( str[arr[i]] == 1)
{
a[i] = arr[i];
}
}
for(i=0 ; i < size ; i++)
{
printf("%d->",a[i]);
}
return 0;
}
still in the new array a,I am getting old data...not sure wats missing here...
Any help would be highly appreciated.
Thanks in advance.
Logical mistakes
the final array won't go till size
the indexing for a is wrong
Simply use one loop to achieve this, analyze following :
int i = 0,j=0;
for( ; i < size ; i++)
{
if(str[arr[i]] == 0 )
{
str[arr[i]]= 1;
a[j++] = arr[i];
}
}
Now iterate till j on final array a

What is wrong with this insertion sort in C?

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include <stddef.h>
void insertionSort(int ar_size, int* ar) {
int i, j;
int temp = 0;
for (i = 1; i < ar_size; i++) {
j = i;
while (j > 0 && ar[i - 1] > ar[i]) {
temp = ar[i - 1];
ar[i - 1] = ar[i];
ar[i] = temp;
j--;
}
}
for (j = 0; j < ar_size; j++) {
printf("%d", ar[j]);
printf(" ");
}
}
int main(void) {
int _ar_size;
scanf("%d", &_ar_size);
int _ar[_ar_size], _ar_i;
for (_ar_i = 0; _ar_i < _ar_size; _ar_i++) {
scanf("%d", &_ar[_ar_i]);
}
insertionSort(_ar_size, _ar);
return 0;
}
I have been trying to look for the error. I cannot see any. What is wrong with this code?
For input as 6 and 4 1 3 5 6 2 , it gives output as 1 3 4 5 2 6. There is one less iteration of the loop but I cannot see why? Please help. Thanks.
You are using index i instead of index j in the internal loop of the function.
while(j>0 && ar[i-1]>ar[i])
{
temp = ar[i-1];
ar[i-1] = ar[i];
ar[i] = temp;
j--;
}
Here everywhere index j has to be used.
Also it is a bad idea that the function also outputs the sorted array. It should do only sorting.
The other bad idea is to use identifiers that start with undescores.
It is better when the first parameter is an array and the second parameter is the size of the array.
The code could look the following way
#include <stdio.h>
void InsertionSort( int *a, int n )
{
int i;
for ( i = 1; i < n; i++ )
{
int j = i;
while ( j > 0 && a[j-1] > a[j] )
{
int tmp = a[j-1];
a[j-1] = a[j];
a[j] = tmp;
--j;
}
}
}
int main(void)
{
int size;
scanf( "%d", &size );
int a[size];
int i;
for ( i = 0; i < size; i++ ) scanf( "%d", &a[i] );
for ( i = 0; i < size; i++ )
{
printf( "%d ", a[i] );
}
puts( "" );
InsertionSort( a, size );
for ( i = 0; i < size; i++ )
{
printf( "%d ", a[i] );
}
puts( "" );
return 0;
}
If the input is
10
2 7 5 4 9 1 4 8 3 5
then output is
2 7 5 4 9 1 4 8 3 5
1 2 3 4 4 5 5 7 8 9
You seem to be using the wrong iterator when pushing the value to the front.
while(j>0 && ar[j-1]>ar[j]) {
temp = ar[j-1];
ar[j-1] = ar[j];
ar[j] = temp;
j--;
}
Try performing a dry run on a piece of paper, it's easy to spot the problem.
for (i = 1; i < ar_size; i++) {
j = i;
while (j > 0 && ar[i-1] > ar[i]) { // problem begins here
temp = ar[i-1];
ar[i-1] = ar[i];
ar[i] = temp;
j--;
}
}
i does not change in the inner loop.
At some point your program swaps 6 with 2 and your sample input list becomes 1 3 4 5 2 6, a[i-1] is 2 and a[i] is 6 and because of ar[i-1] > ar[i] condition the program's flow does not go into the inner loop.
Try this fix:
for (i = 1; i < ar_size; i++) {
j = i;
while (j > 0 && ar[j-1] > ar[j]) {
temp = ar[j-1];
ar[j-1] = ar[j];
ar[j] = temp;
j--;
}
}
The problem with your insertion-sort is you have your j indexes replaced with i indexes in the following code:
while(j>0 && ar[j-1]>ar[j])
{
temp = ar[j];
ar[j] = ar[j-1];
ar[j-1] = temp;
j--;
}
Just a note, when requesting input, it is good practice to print a brief statement describing the input expected. (yes, quick a dirty testing is an exception) It makes if much easier to avoid mistakes with something like:
printf ("enter array size: ");
scanf ("%d", &_ar_size);
int _ar[_ar_size], _ar_i;
for (_ar_i = 0; _ar_i < _ar_size; _ar_i++) {
printf ("enter array element[%d] : ", _ar_i);
scanf ("%d", &_ar[_ar_i]);
}

error sliceShiftLeft() function

#include <stdio.h>
void sliceShiftLeft(int array[], int start, int end) {
if ( start < end ) {
int temp = array[end];
for ( int i = start + 1; i < end; i++ ) {
array[i] = array[i+1];
}
array[start] = temp;
}
}
int main() {
int start = 2;
int end = 5;
int size = 10;
int array[size];
for ( int i = 0; i < size; i++ ) {
array[i] = i;
}
for ( int i = 0; i < size; i++ ) {
printf("%d ", array[i]);
}
printf("\n");
printf("-------------------------\n");
sliceShiftLeft(array, start, end);
for ( int i = 0; i < size; i++ ) {
printf("%d ", array[i]);
}
printf("\n");
return 0;
}
problem is cycle in sliceShiftLeft() function.
i need 01 2345 6789 to be transformed to 01 5234 6789, but i keep getting 01 5455 6789.
my steps:
1) i put the last number in slice to the temp
2) i run cycle for which puts i+1 to i
3) i put the last number, which is in temp, to the first place.
where's my mistake?
If the desired output is the one you mentioned in your question then you are going the wrong way, you should:
store the last element in temp
move all element from start up to end - 1 to the right
store last element into start
While you are going exactly the opposite way, with the exception of third step. What happens is:
0123456789
0134556789 <- array[i] = array[i+1]
0154556789 <- array[start] = temp
your first error is here for(int i ... ) in the fist part of for you mustn't declare a variable but initialize one

Resources