Quicksort giving me two different set of numbers - c

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;
}

Related

Segmentation Fault in Merge Sort in C

I recently tried to implement the merge sort algorithm. I understood the basic concept behind it and even took a peek at one of it's C implementations online but when I try to do it on my own, I always seem to get a segmentation fault.
I am also confused if to use mid or mid+1 in places.
Please help me fix this.
#include <stdio.h>
#include <math.h>
int merge(int arr[], int low, int mid, int high);
int mergeSort(int arr[], int low, int high);
int main(void)
{
int sample[5]={66,7,11,2,99}; //Sample array for sorting.
mergeSort(sample, 0, 4); //Calling the function
}
int merge(int arr[], int low, int mid, int high)
{
if(high>low) //Merge will only work when high is greater than low and mid.
{
int leftSide[mid]; // Dividing the array into two parts, this is the left side; low to mid.
int rightSide[(high-mid)]; //This is the right side; mid to high.
for(int i=0;i<=mid;i++)
{
leftSide[i]=arr[i]; //Filling the leftSide array.
}
for (int x=mid; x<=high; x++)
{
rightSide[x]=arr[x]; //Filling the rightSide array.
}
for(int m,l,r=0; m<=high; m++)
{
if(leftSide[l]>rightSide[r])
{
arr[m]=rightSide[r]; //If the element on rightSide is lesser than on the leftSide then it will come first in the final array.
r++; //Increment the counter so next comparision can begin.
}
else if(leftSide[l]<rightSide[r])
{
arr[m]=leftSide[l]; //If the element on leftSide is lesser than on the rightSide then it will come first in the final array
l++; //Increment the counter so next comparision can begin.
}
else //This will be the case if the numbers are equal
{
if(l<mid) //If the left Index has not reached its maximum limit
{
arr[m]=leftSide[l];
l++;
}
else if(r<(high-mid)) // If the right Index has not reached its maximum limit
{
arr[m]=rightSide[r];
r++;
}
}
}
return 0;
}
else
{
return 1;
}
}
int mergeSort(int arr[], int low, int high)
{
if(high>low)
{
int mid=round((high+low)/2);
mergeSort(arr, low, mid);
mergeSort(arr, mid, high);
merge(arr, low, mid, high);
}
else //Base Case
{
return 1;
}
for(int i=0; i<=high;i++) //Printing the array.
{
printf("%d",arr[i]);
}
return 1;
}
Segmentation fault occur when you access unallocated memory.
In mergeSort function, you called merge function by passing indexes to call merge function.
if(high>low)
{
int mid=round((high+low)/2);
mergeSort(arr, low, mid);
mergeSort(arr, mid, high);
merge(arr, low, mid, high);
}
Inside merge function when you declared leftSide and rightSide arrays, The size of arrays should be index + 1, As array index starts from 0.
int leftSide[mid + 1]; // Dividing the array into two parts, this is the left side; low to mid.
int rightSide[(high-mid) + 1]; //This is the right side; mid to high.
In for(int m,l,r=0; m<=high; m++) the variables m and l are uninitialized. You only set r to 0. This means you will potentially index into arr[] and leftSide[] with illegal indices, causing a segfault.
The variables m, l, r are so called automatic variables, and these are default uninitialized.
Also, when you split arr[] between leftSide[] and rightSide[], you are placing the arr[mid] value into both arrays.

Get a series of lower case letters sorted

The algorithm works fine with integers but since I converted them into char, it has been printing null for the output:
/* sort a series of lower case letters using quicksort algorithm. */
#include <stdio.h>
#define N 10
// since c gets the ascii code when returning an int for a char variable.
char quicksort(char a[], char low, char high);
char split(char a[], char low, char high);
int a[N];
int main(void)
{
int i;
printf("Enter letters to be sorted: ");
for (i = 0; i < N; i++)
scanf("%d", &a[i]);
quicksort(a, 0, N - 1);
printf("In sorted order: ");
for (i = 0; i < N; i++)
printf("%s ", a[i]);
printf("\n");
return 0;
}
char quicksort(char a[], char low, char high)
{
int middle;
if (low >= high) return;
middle = split(a, low, high);
quicksort(a, low, middle - 1);
quicksort(a, middle + 1, high);
}
char split(char a[], char low, char high)
{
char part_element = a[low];
for (;;) {
while (low < high && part_element <= a[high])
high--;
if (low >= high) break;
a[low++] = a[high];
while (low < high && a[low] <= part_element)
low++;
if (low >= high) break;
a[high--] = a[low];
}
a[high] = part_element;
return high;
}
Three issues:
a is declared as an array of int, but all your functions handle an array of char. This means they won't iterate through the array correctly. Change it to char a[N].
To read a character, use the %c format specifier to scanf.
To print a character, use the %c format specifier to printf.
The revised code still doesnt work and i cant seem to find the bug.
Your problems appear to be with main() pretty much along the lines that other folks have suggested with respect to using char oriented data instead of int. There are some non fatal questionable choice issues like using char datatypes for array indexes; quicksort() is declared to return char but returns nothing; and so forth. Below is a rework of your code, mostly for style, incorporating various folks suggestions:
/* sort a series of letters using quicksort algorithm. */
#include <stdio.h>
#define N (10)
void quicksort(char a[], int low, int high);
int split(char a[], int low, int high);
int main(void)
{
char a[N];
printf("Enter letters to be sorted: ");
for (int i = 0; i < N; i++) {
scanf("%c", &a[i]);
}
quicksort(a, 0, N - 1);
printf("In sorted order: ");
for (int i = 0; i < N; i++) {
printf("%c ", a[i]);
}
printf("\n");
return 0;
}
void quicksort(char a[], int low, int high)
{
if (low < high) {
int middle = split(a, low, high);
quicksort(a, low, middle - 1);
quicksort(a, middle + 1, high);
}
}
int split(char a[], int low, int high)
{
char part_element = a[low];
for (;;) {
while (low < high && part_element <= a[high]) {
high--;
}
if (low >= high) {
break;
}
a[low++] = a[high];
while (low < high && a[low] <= part_element) {
low++;
}
if (low >= high) {
break;
}
a[high--] = a[low];
}
a[high] = part_element;
return high;
}
Does it not do everything it's supposed to?
EXAMPLE
> ./a.out
Enter letters to be sorted: aadircslne
In sorted order: a a c d e i l n r s
>
scanf requires a %c format specifier. Your scanf should change to
scanf("%c", &a[i]);
As a result, you should redeclare the a array to char, not int.

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…

How can I make this recursive Binary Search program exit and not crash if the number is not found?

How can I prevent this program from crashing if the value the user searched for is not found? (When I try to implement an if/else or count system, the program doesn't work correctly)
#include <stdio.h>
#include "simpio.h"
#include "genlib.h"
#define start 0
void bubble(int numbers[]);
int binary(int val, int numbers[], int low, int high);
void io(int numbers[]);
int size;
main()
{
int result, search;
printf("This program sorts and searches an array\n");
printf("How many numbers would you like to sort and search?\n");
size = GetInteger()-1;
int numbers[size];
printf("Enter the numbers\n");
io(numbers);
bubble(numbers);
printf("Which number would you like to search for?\n");
search = GetInteger();
result = binary(search,numbers,start,size);
printf("The number %d was found at index %d\n",search,result+1);
}
void io(int numbers[])
{
int ink;
for(ink=0;ink<=size;ink++)
{
numbers[ink] = GetInteger();
}
}
void bubble(int numbers[])
{
int first,second,count,swap;
while(TRUE)
{
for(first=0,second=1,count=0;second<=size;first++,second++)
{
if(numbers[first]>numbers[second])
{
count++;
swap = numbers[first];
numbers[first]= numbers[second];
numbers[second] = swap;
}
}
if(count==0)break;
}
}
int binary(int val, int numbers[], int low, int high)
{
int mid;
mid = (low+high)/2;
if(val==numbers[mid]||low>high) return mid;
if(val>numbers[mid]) return(binary(val,numbers,mid,high));
else if(val<numbers[mid]) return(binary(val,numbers,low,mid));
}
change to
size = GetInteger();
int numbers[size--];//change size to max index
//..
int binary(int val, int numbers[], int low, int high)
{
int mid;
if(low>high)//if not found!
return -1;//check return value at main
mid = (low+high)/2;
if(val==numbers[mid]) return mid;
if(val>numbers[mid]) return(binary(val,numbers,mid+1,high));
else if(val<numbers[mid]) return(binary(val,numbers,low,mid-1));
}

Assignment makes pointer without a cast

I am editing a quick sort code so that the values of low, high, and middle point to an array element instead of integers.
This is my code:
#include <stdio.h>
#define N 10
void quicksort(int a[], int *low, int *high);
int split(int a[], int *low, int *high);
int main(void)
{
int a[N], i;
printf("Enter %d numbers to be sorted: ", N);
for (i=0; i<N; i++)
scanf("%d", &a[i]);
quicksort(a, &a[0], &a[N-1]);
printf("In sorted order: ");
for (i=0; i<N; i++)
printf("%d ", a[i]);
printf("\n");
return 0;
}
void quicksort(int a[], int *low, int *high)
{
int *middle;
if (low >= high) return;
middle = split(a, low, high);
quicksort(a, low, middle - 1);
quicksort(a, middle + 1, high);
}
int split(int a[], int *low, int *high)
{
int part_element = *low;
for (;;) {
while (low < high && part_element <= *high)
high--;
if (low >= high) break;
*low++ = *high;
while (low < high && *low <= part_element)
low++;
if (low >= high) break;
*high-- = *low;
}
*high = part_element;
return *high;
}
I'm getting the error message:
qs.c:32:12: warning: assignment makes pointer from integer without a cast [enabled by default]
middle = split(a, low, high);
^
Can someone help me with this? Still a beginner at programming. All types of help are appreciated.
The problem is in this statement.
middle = split(a, low, high);
because middle is a pointer variable whereas split is a function which returns integer value not a pointer to an integer.
You are assigning integer value to a pointer variable middle .
You are not allowed to do that. :)
May be this will help you.
Change 'split()' to return an 'int *' instead of 'int'.
Change the last line of the 'split()' function from:
return *high;
to
return high;
Perhaps this would work better:
#include <stdio.h>
#define N 10
void quicksort(int a[], int *low, int *high);
int *split(int a[], int *low, int *high);
int main(void)
{
int a[N], i;
printf("Enter %d numbers to be sorted: ", N);
for (i=0; i<N; i++)
scanf("%d", &a[i]);
quicksort(a, &a[0], &a[N-1]);
printf("In sorted order: ");
for (i=0; i<N; i++)
printf("%d ", a[i]);
printf("\n");
return 0;
}
void quicksort(int a[], int *low, int *high)
{
int *middle;
if (low >= high) return;
middle = split(a, low, high);
quicksort(a, low, middle - 1);
quicksort(a, middle + 1, high);
}
int *split(int a[], int *low, int *high)
{
int part_element = *low;
for (;;) {
while (low < high && part_element <= *high)
high--;
if (low >= high) break;
*low++ = *high;
while (low < high && *low <= part_element)
low++;
if (low >= high) break;
*high-- = *low;
}
*high = part_element;
return high;
}

Resources