Segmentation Fault in my Quick Sort Program in C? - c

I'm Getting Segmentation fault by debugger in partition() function at commented variable...following code is a complete implementation of Quick Sort algorithm.
// Sorting Algorithms
void quick_sort(int arr[],int length);
int partition(int a[],int low, int high);
void quick_sort_recursion(int arr[], int low, int high);
void swap(int *x, int *y);
void quick_sort(int arr[],int length){
quick_sort_recursion(arr,0,length-1);
}
void quick_sort_recursion(int arr[],int low, int high){
if(low<high){
int pivot_value = partition(arr,low,high);
quick_sort_recursion(arr,low,pivot_value - 1);
quick_sort_recursion(arr,pivot_value+1,high);
}
}
int partition(int arr[], int low, int high){
int pivot_value = arr[high]; //getting 'segmentation fault' here
int i = low;
for (int j = low; j < high; j++)
{
if(arr[j] <= pivot_value){
swap(&arr[i],&arr[j]);
i++;
}
}
swap(&arr[i],&arr[high]);
}
see image here...

In the image, the high value (6422295) is quite large as for the size of array. The large size array would lead to the segmentation fault.

Related

quicksort implementation trouble

I am encountering the problems in executing the quicksort algorithm.
THere is a error i am encountering but unable to find where the problem is. if someone could point where the error is i will be thankfull.
#include <stdio.h>
#include <stdlib.h>
void main(){
int arr[] = {10, 7, 8, 9, 1, 5};
int n = sizeof(arr)/sizeof(arr[0]);
quickSort(arr,0,n-1);
printArray(arr,0,n-1);
}
//Quicksort Function
void quickSort(int arr[],int low,int high){
if (low < high){
int pi=partition(arr,low,high);
quickSort(arr,low,pi-1);//takes care of lower set of numbers
quickSort(arr,pi+1,high);//takes care of higher elements above pivot
}
}
//Function for partitioing, in my program i am cosidering pivot as the element at high or the last element
int partition(int arr[],int low,int high){
int i,j;
i=(low-1);
int pivot=arr[high];
for(j=low;j<=high;j++){
if(arr[j]<=pivot){
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i+1], &arr[high]);
return (i+1);
}
//function to print array
void printArray(int arr[],int low,int high){
int i;
for(i=low;i<=high;i++){
printf("%d ",arr[i]);
}
}
//function to swap two elements of array
void swap(int* a, int* b)
{
int t = *a;
*a = *b;
*b = t;
}
The Simple Implementation of QuickSort Algorithm
void q_sort(int v[],int left,int right)
{
int i,last;
if(left>=right)
return;
swap(v,left,(left+right)/2);
last=left;
for(i=left+1;i<=right;i++)
if(v[i]<v[left])
swap(v,++last,i);
swap(v,left,last);
q_sort(v,left,last-1);
q_sort(v,last+1,right);
}
void swap(int v[],int i,int j)
{
int temp;
if(i!=j){
temp=v[i];
v[i]=v[j];
v[j]=temp;
}
}
The problem is in this statement of your partition() -
if(arr[j]<=pivot){
Change it to -
if(arr[j]<pivot){

Quicksort giving me two different set of numbers

Hi i've written a quick program testing the quicksort to see if i understand it fully but it seems like sorting different array. I assume i need to type of pointer? It also seems like the sorted array randomising quite a bit of 0's. Is there something wrong with the code?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 150
void quickSort(int array[], int low, int high); // sorting algorithm
int split(int array[], int low, int high); // spit the array
int main(void)
{
int array[MAX];
int i;
srand((unsigned)time(NULL));
for (i=0;i<MAX;i++)
{
array[i] = rand()%MAX;
printf("#%d:[%d]\n", i+1, array[i]);
quickSort(array, 0, MAX-1);
}
printf("The sorted order:\n");
for(i=0;i<MAX;i++)
{
printf("#%d:[%d]\n", i+1,array[i]);
}
return 0;
}
// function
void quickSort(int array[], int low, int high) // sorting algorithm
{
int middle;
if (low >= high)
{
return;
}
middle = split(array, low, high);
quickSort(array, low, middle-1);
quickSort(array, middle+1, high);
}
int split(int array[], int low, int high)
{
int partElement = array[low];
for(;;)
{
while (low < high && partElement <= array[high])
{
high--;
}
if (low>= high)
{
break;
}
array[low++]=array[high];
while (low < high && array[low] <= partElement)
{
low++;
}
if (low >= high)
{
break;
}
array[high--] = array[low];
}
array[high] = partElement;
return high;
}

Why changing random number generator changes running time of quick sort in C

I'm written a quick sort implementation in C. Changing the rand function range(using the remainder) in the first loop changes the running time of the algorithm dramatically. As it is right now, the algorithm takes 43 seconds. Changing the range from 100 to 10000 reduces the running to 0.9 seconds.
Why is that?
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void quick_sort(int array[], int low, int high);
int partition(int array[], int low, int high);
void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int main(void)
{
const int len = 1000000;
srand(time(NULL));
int array[len];
puts("Populating the array...\n");
for(int i = 0; i < len; i++)
array[i] = rand() % 100; // Changing this line dramatically reduce the running time
puts("|Now sorting the array...|\n");
quick_sort(array, 0, len-1);
/*for(int i = 0; i < len; i++)*/
/*printf("%d ", array[i]);*/
}
void quick_sort(int array[], int low, int high)
{
int j;
if(low < high)
{
j = partition(array, low, high);
quick_sort(array, low, j-1);
quick_sort(array, j+1, high);
}
}
int partition(int array[], int low, int high)
{
int pivot = array[high];
int leftwall = low-1;
for(int i = low; i < high; i++)
{
if(array[i] <= pivot)
{
++leftwall;
swap(&array[leftwall], &array[i]);
}
}
swap(&array[leftwall+1], &array[high]);
return ++leftwall;
}
My guess is that when partitioning the array you end up moving a large number of duplicate values. When you pick the random numbers from only 100 choices, the array of a million elements will have about 10,000 of each value. It looks like you'll be swapping them around every call to partition due to the array[i] <= pivot comparison. For example, when you are almost done and a partition has only two distinct values in it, it still has about 20,000 elements…

Mergesort implementation in C

Can someone please check my mergesort code. When I tried sorting the input values, the sorted array contained random values which weren't from input. And they were not sorted.
Is the way I'm declaring array within the while loop correct?
#include <stdio.h>
void merge (int a[], int aux[], int lo, int mid, int hi){
for(int y=lo; y<=hi; y++){
aux[y]=a[y];
}
int i=lo;
int j=mid+1;
for(int k=lo;k<=mid;k++){
if (j>hi) a[k]=aux[i++];
else if (i>mid) a[k]=aux[j++];
else if (a[j]<a[i])
a[k]= aux[j++];
else
a[k]=aux[i++];
}
return;
}
void sort (int b[],int aux[], int lo, int hi)
{
if(hi<=lo)
return;
int mid= lo+(hi-lo)/2;
sort(b, aux, mid+1, hi);
sort(b, aux, lo, mid);
merge(b,aux,lo,mid,hi);
return;
}
int main(void) {
int t,n;
long long int sum;
scanf("%d",&t);
while(t--){
sum=0;
scanf("%d",&n);
int w[n];
int m[n];
int g[n];
int h[n];
for (int i=0; i<n;i++){
scanf("%d",&m[i]);
}
for (int j=0; j<n;j++){
scanf("%d",&w[j]);
}
sort(w,g,0,n-1);
sort(m,h,0,n-1);
}
return 0;
}
You are compareing meaningless values in the merge funtion and stop the merging in the middle of the processs.
To correct them, in the merge function
Change k<=mid to k<=hi
Change a[j]<a[i] to aux[j]<aux[i]

Mergesort, using a for loop to do merge

I am trying to write the code in C for mergesort using for loop in the merge function. Unfortunately it is not working. In the main function I create an array on 10 ints in descending order and then I call the mergesort function to sort them. There is obviously an error in the merge function, since the ascending order is never realized and in some array sizes some long numbers intrude. What am I doing wrong? Here's the function:
#include <stdio.h>
#include <stdlib.h>
void mergesort(int array[], int left, int right);
int main()
{
int i;
int arr[10];
for(i=10;i>0;i--){
arr[10-i]=i;
}
for(i=0;i<10;i++){
printf("arr[%d] = %d\n",i,arr[i]);
}
mergesort(arr,0,9);
puts("\n");
for(i=0;i<10;i++){
printf("arr[%d] = %d\n",i,arr[i]);
}
return 0;
}
void mergesort(int array[], int left, int right)
{
void merge(int array[],int left, int mid, int right);
int mid;
if(left<right){
mid=(left+right)/2;
mergesort(array,left,mid);
mergesort(array,mid+1,right);
merge(array,left,mid,right);
}
}
void merge(int array[], int left, int mid, int right)
{
int i;
int l=0;
int r=mid+1;
int arr_sorted[10];
for(i=0;i<=right;i++){
if((l<=mid) && (r<=right)){
if(array[l]<array[r]){
arr_sorted[i]=array[l];
l++;
}
else {
arr_sorted[i]=array[r];
r++;
}
}
if(l>mid){
arr_sorted[i]=array[r];
r++;
}
if(r>right){
arr_sorted[i]=array[l];
l++;
}
}
for(i=0;i<=right;i++){
array[i]=arr_sorted[i];
}
}
First that is looking strange is why you are passing left parameter to the merge, but iterate from 0 to right; left is not even using in this function.
Some corrections that were needed in the merge function :
void merge(int array[], int left, int mid, int right)
{
int i;
int l=left; //If you are passing left, then it should be used here !!
int r=mid+1;
int arr_sorted[10];
for(i=0;(l<=mid)&&(r<=right);i++){
//Your condition for this loop unnecessarily complicates the rest of the code. This is a better way to go about it
//The loop body is fine
if(array[l]<array[r]){
arr_sorted[i]=array[l];
l++;
}
else {
arr_sorted[i]=array[r];
r++;
}
}
//Now, checking for remaining elements and adding them to the result
//The conditions are simple because of the test condition we used in the previous for loop
if(l>mid){
for(;r<=right;r++,i++) arr_sorted[i]=array[r];
}
if(r>right){
for(;l<=mid;l++,i++) arr_sorted[i]=array[l];
}
}
for(i=0;i<=right;i++){
array[i]=arr_sorted[i];
}
}
Also, as a matter of style, try to keep your forward declarations in one place (more so as the functions are related). Instead of :
void mergesort(int array[], int left, int right)
{
void merge(int array[],int left, int mid, int right);//This line should be moved to the top with the mergesort forward declaration
int mid;
if(left<right){
mid=(left+right)/2;
Try doing :
#include <stdio.h>
#include <stdlib.h>
void mergesort(int array[], int left, int right);
void merge(int array[],int left, int mid, int right); // <--------
This is just a matter of preference, though.
here is the entire working merge sort, you can see the differences, let me know if you have any further questions. I had to change the name because stdlib has mergesort implementation.
#include <stdio.h>
#include <stdlib.h>
int mymergesort(int array[], int left, int right);
int main()
{
int i;
int arr[10];
for(i=10;i>0;i--){
arr[10-i]=i;
}
for(i=0;i<10;i++){
printf("arr[%d] = %d\n",i,arr[i]);
}
mymergesort(arr,0,9);
puts("\n");
for(i=0;i<10;i++){
printf("arr[%d] = %d\n",i,arr[i]);
}
return 0;
}
int mymergesort(int array[], int left, int right)
{
void mymerge(int array[],int left, int mid, int right);
int mid;
mid=(left+right)/2;
if(left<right){
mymergesort(array,left,mid);
mymergesort(array,mid+1,right);
mymerge(array,left,mid,right);
}
return 0;
}
void mymerge(int array[], int left, int mid, int right)
{
int i=0;
int l=left;
int r=mid+1;
int arr_sorted[10];
for(i=left;i<=right;){
if((l<=mid) && (r<=right)){
if(array[l]<array[r]){
arr_sorted[i]=array[l];
l++;
i++;
}
else {
arr_sorted[i]=array[r];
r++;
i++;
}
}
if(l>mid){
for(;r<=right;r++){
arr_sorted[i]=array[r];
i++;
}
break;
}
if(r>right){
for(;l<=mid;l++){
arr_sorted[i]=array[l];
i++;
}
break;
}
}
for(i=left;i<=right;i++){
array[i]=arr_sorted[i];
}
}

Resources