I was trying to code a quick sort program in c, and my recursive function is in an infinite loop.
The problem is:
You have been given an array
A of size
N.This array contains integers ranging from
1 to
10^9. You need to sort the contents of this array by their value and then print the contents of it.
Input Format:
The first line contains a single integers N denoting the size of the array. The next line contains N space separated integers denoting the contents of the array.
Output Format:
Print N space separated integers, i.e. the final sorted array.
Constraints:
1≤N≤10^6
1≤A[i]≤10^9
void fill_vet(unsigned int a[], unsigned int n){
int i;
for(i=0; i<n; i++)
scanf("%u", &a[i]);
}
void print_vet(unsigned int a[], unsigned int n){
int i;
for(i=0; i<n; i++)
printf("%u ", a[i]);
}
int partition(unsigned int a[], int start, int end){
int i, j;
unsigned int pivot, n_swap;
i = start + 1;
pivot = a[start];
for(j = start+1; j<=end; j++){
if(a[j] < pivot){
n_swap = a[j];
a[j] = a[i];
a[i] = n_swap;
i++;
}
}
n_swap = a[i-1];
a[i-1] = a[start];
a[start] = n_swap;
return i-1;
}
void sort_array(unsigned int a[], int start, int end){
while(start < end){
int pos_piv = partition(a, start, end);
sort_array(a, start, pos_piv-1);
sort_array(a, pos_piv+1, end);
}
}
int main()
{
unsigned int n, a[100000];
scanf("%u", &n);
fill_vet(a, n);
sort_array(a, 0, n-1);
print_vet(a, n);
return 0;
}
Can you tell me where is the error pls!
You are using recursion so you don't need a loop:
void sort_array(unsigned int a[], int start, int end){
if(start < end){
int pos_piv = partition(a, start, end);
sort_array(a, start, pos_piv-1);
sort_array(a, pos_piv+1, end);
}
}
Related
The code does run. This is a little different version of quicksort I am working on. I am running into some major issues with it. First off It prints out the first element in the array as n: for example(if you set n = 3, even if you make the first element in the array 1 lets say, it will still print out 3 as the first element). Also when you print out the sorted version it doesn't actually change anything.
Example input with n = 3,
Set values = 8 , 7 , 6
Initial output will equal 3 , 7 , 6
Final output will equal 3 , 7 , 6
(The output SHOULD be 6 , 7 , 8)
I haven't been able to find any code online similar to my code, so this may be something new! Thanks.
//preprocessor directives and header files
#include <stdio.h>
#define MAX_ARRAY_SIZE 50
//function prototypes separated by data types
void print_array( int array[], int n ); // Print out the array values
void swap( int array[], int index1, int index2 ); // Swap two array elements.
void quicksort( int array[], int low, int high ); // Sorting algorithm
int populate_array( int array[] ); // Fill array with values from user.
int partition( int array[], int low, int high ); // Find the partition point (pivot)
//the main function
int main(void)
{
int array[MAX_ARRAY_SIZE];
//set n = to size of user created size of array
int n = populate_array(&array[MAX_ARRAY_SIZE]);
//print the original array to the screen
print_array(&array[MAX_ARRAY_SIZE], n );
//perform the algorithm
quicksort(array, 0, n-1);
printf("The array is now sorted:\n");
print_array(&array[MAX_ARRAY_SIZE], n);
return 0;
}
// *array and array[] are the same...
int populate_array(int array[])
{
int n = -1;
printf("Enter the value of n > ");
scanf("%d", &n);
if(n > MAX_ARRAY_SIZE)
{
printf("%d exceeds the maximum array size. Please try again.\n\n", n);
populate_array( &array[MAX_ARRAY_SIZE]);
}
else if(n < 0)
{
printf("%d is less than zero. Please try again.\n\n", n);
populate_array( &array[MAX_ARRAY_SIZE]);
}
else if(n == 0)
{
printf("%d Array of size 0? Please don't try this, and... Please try again.\n\n", n);
populate_array( &array[MAX_ARRAY_SIZE]);
}
else
{
for(int i = 0; i < n; i++)
scanf("%d", &array[i]);
}
printf("The initial array contains: \n");
return n;
}
void print_array(int array[], int n)
{
for(int i = 0; i < n; i++)
printf("%+5d\n", array[i]);
}
void quicksort(int array[], int low, int high)
{
if (low < high)
{
/* pivot is partitioning index, array[p] is now
at right place */
int pivot = partition(array, low, high);
// Separately sort elements before
// partition and after partition
quicksort(array, low, pivot - 1);
quicksort(array, pivot + 1, high);
}
}
int partition(int array[], int low, int high)
{
int pivot = array[high];
int i = low;
for (int j = low; j <= high- 1; j++)
{
// If current element is smaller than or
// equal to pivot
if (array[j] <= pivot)
{
swap(array, i, j);
i = i +1;
}
}
swap(array, i, high);
return i;
}
void swap(int array[], int index1, int index2)
{
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
Here is a heavily commented answer. I changed the code quite a bit.
This is now a fully functional quicksort array for user input.
The problem I was having before was with the &array[MAX_ARRAY_SIZE]. This needed to be changed to just "array" instead. The &array[MAX_ARRAY_SIZE] was trying to access a memory location past the actual size of the array.
Changing it to just "array" means that it is accessing the first element in the array.(Correct if wrong)
I also changed the populate array function to be a robust do-while loop. And instead of trying to re-call the function inside itself. The do-while loop will only allow you to change the value of 'n'.
/*
Author: Zachary Alberda
*/
//preprocessor directives and header files
#include <stdio.h>
#define MAX_ARRAY_SIZE 50
//function prototypes separated by data types
void print_array( int array[], int n ); // Print out the array values
void swap( int array[], int index1, int index2 ); // Swap two array elements.
void quicksort( int array[], int low, int high ); // Sorting algorithm
int populate_array( int array[] ); // Fill array with values from user.
int partition( int array[], int low, int high ); // Find the partition point (pivot)
//the main function
int main(void)
{
int array[MAX_ARRAY_SIZE]; //set n = to size of user created size of array
int n = populate_array(array); //print the original array to the screen
print_array(array, n ); //print array of size n
quicksort(array, 0, n-1); //perform the algorithm low is 0, high is size of array -1.
printf("The array is now sorted:\n");//Inform user that the array is sorted.
print_array(array, n);//print the sorted array
return 0; // exit without errors.
}
// *array and array[] are the same...
int populate_array(int array[])
{
int n = -1;//initialize variable n(local variable to function populate_array)
printf("Enter the value of n > ");//inform user of what to input
scanf("%d", &n);
/*
CHECK IF N IS VALID
This is a robust do while loop!
1) Performs the if-statements while 'n' is not valid in a do-while loop.
-The reason I do this is because it will cause errors
if the if-statements are individual without the do-while loop.
2)The program will not crash if you try different combinations
of inputs for 'n'. :)
3)Checks if user input is > MAX_ARRAY_SIZE
4)Checks if user input is < 0
5)Checks if user input is == 0
*/
do
{
if(n > MAX_ARRAY_SIZE)
{
printf("%d exceeds the maximum array size. Please try again.\n\n", n);
printf("Enter the value of n > ");
scanf("%d", &n);
}
else if(n < 0)
{
printf("%d is less than zero. Please try again.\n\n", n);
printf("Enter the value of n > ");
scanf("%d", &n);
}
else if(n == 0)
{
printf("%d Array of size 0? Please don't try this, and... Please try again.\n\n", n);
printf("Enter the value of n > ");
scanf("%d", &n);
}
}while(n <= 0 || n > MAX_ARRAY_SIZE);
//scan in array if user input is valid
for(int i = 0; i < n; i++)
scanf("%d", &array[i]);
printf("The initial array contains: \n");//Inform user of initial array
return n;
}
void print_array(int array[], int n)
{
//print array in pre/post order before and after the algorithm.
for(int i = 0; i < n; i++)
printf("%+5d\n", array[i]);
}
void quicksort(int array[], int low, int high)
{
if (low < high)
{
/* pivot is partitioning index, array[pivot] is now
at right place */
int pivot = partition(array, low, high);
// Separately sort elements before
// partition and after partition
quicksort(array, low, pivot - 1);
quicksort(array, pivot + 1, high);
}
}
int partition(int array[], int low, int high)
{
int pivot = array[high];
int i = low;
for (int j = low; j <= high- 1; j++)
{
// If current element is smaller than or
// equal to pivot
if (array[j] <= pivot)
{
swap(array, i, j);
i = i +1;
}
}
swap(array, i, high);
return i;
}
void swap(int array[], int index1, int index2)
{
//swap positions of array index 1 and 2
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
My code works properly when all variables and array are defined as int, but if I change the type to unsigned int, it won't work.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
void swap(unsigned int *a, unsigned int *b){
unsigned int temp;
temp=*a ; *a=*b ; *b=temp;
}
void heapify(unsigned int A[], unsigned int i, unsigned int n){
//sort from root i
unsigned int L = 2*i+1;
// node left child
unsigned int R = 2*i+2;
//node right child
unsigned int max = i;
//set max node is root
if(L < n && A[L] > A[max]) max = L;
//if node child > max, set that node is max
if(R < n && A[R] > A[max]) max = R;
if(max != i) {
swap(&A[i], &A[max]);
heapify(A, max, n);//recursive tree with root is node swaped
}
}
void buildHeap(unsigned int A[], unsigned int n){
unsigned int i = n/2 - 1;
for(; i >= 0; i--) heapify(A, i, n);
}
void heapSort(unsigned int A[], unsigned int n){
buildHeap(A, n);
unsigned int i = n-1;
for(; i >= 0; i--){
swap(&A[0], &A[i]);
heapify(A, 0, i);
}
}
void PrintArray(unsigned int A[], unsigned int n){
unsigned int i;
for(i = 0; i < n; i++){
printf("%d ", A[i]);
}
}
int main(){
unsigned int A[]={1,6,8,9,7,1,65,92,2,9,2,5,73,9,1,5};
unsigned int n=sizeof (A)/sizeof(unsigned int);
PrintArray(A,n);
heapSort(A,n);
PrintArray(A,n);
}
The output is stuck at print the old array and nothing happens after that.
What should I do?
The problem is at buildHeap - you set your iterator as unsigned int, and run a loop until i is no longer positive - which in the cash of unsigned int will never happen.
void buildHeap(unsigned int A[], unsigned int n){
unsigned int i = n/2 - 1;
for(; i >= 0; i--) heapify(A, i, n);
}
I am testing my quicksort code in C(which calculates the number of swaps that this function has to make while sorting), which is not providing correct result.
I narrowed it down to my swap function.When swap function get first = 3 and second = 3.Its final result becomes first = 0 and second = 0.
When tested separatly this function works fine.Below is the code
#include<stdio.h>
#define SIZE 5
int arr[SIZE];
void quicksort(int start, int end);
long int answer = 0;
int main(){
int i, input;
for(i = 0; i < SIZE; i++){
scanf("%d",&arr[i]);
}
quicksort(0, SIZE - 1);
printf("%ld\n", answer);
return 0;
}
void quicksort(int start, int end){
void swap(int * first, int * second);
int partition(int start, int end);
int pos;
if(start >= end)return;
else{
pos = partition(start, end);
quicksort(start, pos - 1);
quicksort(pos + 1, end);
answer += (end - start);
}
}
void swap(int * first, int * second){
printf("start = %d , end = %d\n",*first, *second);
*first = *first ^ *second;
*second = *first ^ *second;
*first = *first ^ *second;
printf("start = %d , end = %d\n",*first, *second);
}
int findpivot(int start, int end){
return start;
}
int partition(int start, int end){
int findpivot(int start, int end);
int i = 0;
int pivot_pos = findpivot(start, end);
int pivot = arr[pivot_pos];
int pos = pivot_pos + 1;
for(i = pivot_pos + 1 ; i <= end; i++){
if(arr[i] <= pivot){
swap(&arr[i], &arr[pos]);
pos++;
}
}
pos--;
for(i = 0; i < SIZE; i++){
printf("%d ",arr[i]);
}
printf("\n");
swap(&arr[pivot_pos], &arr[pos]);
for(i = 0; i < SIZE; i++){
printf("%d ",arr[i]);
}
printf("getting out\n");
return pos;
}
From programmers.stackexchange.com/a/182043
When using xorswap there's a danger of supplying same variable as both arguments to the function which zeroes out the said variable due to it being xor'd with itself which turns all the bits to zero. Of course this itself would result in unwanted behavior regardless of algorithm used, but the behavior might be surprising and not obvious at first glance.
So your fix is to check if both arguments are equal.
I have written a program which generates a random array and sorts it by using both the insertion and quicksort algorithms. The program also measures the runtime of each function. The size of the array is defined in the preamble as a parameterised macro L. My question is:
How can I test both sorting algorithms with arrays of various sizes in a single execution?
I want my program to sort arrays of size L=10, 100, 1000, 5000 and 10000 in one execution. My program code is detailed below.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//Random Array Length
#define MAX 100
#define L 10
void naive_sort(int[]);
void smarter_sort(int[],int,int);
void swap(int[],int,int);
int choose_piv(int[],int,int);
int main(){
int i, a[L], b[L];
clock_t tic, toc;
//Generate an array of random numbers
for(i=0; i<L; i++)
a[i]= rand() % (MAX+1);
//Define b identical to a for fair comparison
for(i=0; i<L; i++)
b[i]=a[i];
//Unsorted Array
printf("\nUnsorted array: ");
for(i=0; i<L; i++)
printf("%d ", a[i]);
//Insertion Sort (1e)
tic = clock();
naive_sort(a);
printf("\nInsertion Sort: ");
for(i=0; i<L; i++)
printf("%d ", a[i]);
toc = clock();
printf(" (Runtime: %f seconds)\n", (double)(toc-tic)/CLOCKS_PER_SEC);
//Quicksort (1f)
tic = clock();
smarter_sort(b,0,L-1);
printf("Quicksort: ");
for(i=0; i<L; i++)
printf("%d ", b[i]);
toc = clock();
printf(" (Runtime: %f seconds)\n", (double)(toc-tic)/CLOCKS_PER_SEC);
return 0;
}
void naive_sort(int a[]){
int i, j, t;
for(i=1; i < L; i++){
t=a[i];
j=i-1;
while((t < a[j]) && (j >= 0)){
a[j+1] = a[j];
j--;
}
a[j+1]=t;
}
}
void smarter_sort(int a[], int l, int r){
if(r > l){
int piv = choose_piv(a, l, r);
smarter_sort(a, l, piv-1);
smarter_sort(a, piv+1, r);
}
}
void swap(int a[], int i, int j){
int t=a[i];
a[i]=a[j];
a[j]=t;
}
int choose_piv(int a[], int l, int r){
int pL = l, pR = r;
int piv = l;
while (pL < pR){
while(a[pL] < a[piv])
pL++;
while(a[pR] > a[piv])
pR--;
if(pL < pR)
swap(a, pL, pR);
}
swap(a, piv, pR);
return pR;
}
I would appreciate any feedback.
EDIT: I modified the code as suggested, and it worked for the small values. But for the quicksort case L=100 and beyond it, I don't get any output:
and as you can see, the few outputs I get are zero. What's wrong with the code?
/*
* Task 1, question h
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//Random Array Length
#define MAX 100
void perf_routine(int);
void naive_sort(int[],int);
void smarter_sort(int[],int,int);
void swap(int[],int,int);
int choose_piv(int[],int,int);
int main(){
perf_routine(10);
perf_routine(100);
perf_routine(1000);
perf_routine(5000);
perf_routine(10000);
return 0;
}
void perf_routine(int L){
int i, a[L], b[L];
clock_t tic, toc;
printf("Arrays of Length %d:\n", L);
//Generate an array of random numbers
for(i=0; i<L; i++)
a[i]= rand() % (MAX+1);
//Define b identical to a for fair comparison
for(i=0; i<L; i++)
b[i]=a[i];
//Insertion Sort (1e)
tic = clock();
naive_sort(a, L);
toc = clock();
printf("Insertion Sort Runtime: %f seconds\n", (double)(toc-tic)/CLOCKS_PER_SEC);
//Quicksort (1f)
tic = clock();
smarter_sort(b,0,L-1);
toc = clock();
printf("Quicksort Runtime: %f seconds\n", (double)(toc-tic)/CLOCKS_PER_SEC);
}
void naive_sort(int a[], int L){
int i, j, t;
for(i=1; i < L; i++){
t=a[i];
j=i-1;
while((t < a[j]) && (j >= 0)){
a[j+1] = a[j];
j--;
}
a[j+1]=t;
}
}
void smarter_sort(int a[], int l, int r){
if(r > l){
int piv = choose_piv(a, l, r);
smarter_sort(a, l, piv-1);
smarter_sort(a, piv+1, r);
}
}
void swap(int a[], int i, int j){
int t=a[i];
a[i]=a[j];
a[j]=t;
}
int choose_piv(int a[], int l, int r){
int pL = l, pR = r;
int piv = l;
while (pL < pR){
while(a[pL] < a[piv])
pL++;
while(a[pR] > a[piv])
pR--;
if(pL < pR)
swap(a, pL, pR);
}
swap(a, piv, pR);
return pR;
}
I would, in each function gives the length of the array in parameters and make sure you don't try to reach element outside of array, for example swap would become:
int swap(int *a, int length, int i, int j)
{
if(i>=length || j>=length)
return -1;
int t=a[i];
a[i]=a[j];
a[j]=t;
return 0;
}
Also note the return -1 or 0 to indicates a failure. Apply that to the rest of the code and you'll have something that can be applied to any array.
When arrays are passed to functions, they are passed as (or "decay into") pointer to their first element. There is no way to know about the size of the array.
It is therefore very common to pass the actual length as additional parameter to the function. An example of your naive sort with three arrays of different size if below.
Of course, one must take care to keep the array and length in sync. Passing a length that is too big may result in undefined behaviour. For example, calling fill(tiny, LARGE) in the example below may result in disaster.
(Aside: An array may have a maximum length or capacity and an actual length. For example if you want to read up to ten numbers from a file, you must pass an array of length 10, but if there are only four numbers read, you are dealing with two additional parameters here: the possible array length, 10, and the actual length, 4. That's not the case here, though.)
Well, here goes. All three array functions have the same signature: They take an array and its length.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
void sort(int a[], size_t len)
{
size_t i, j;
for (i = 1; i < len; i++) {
int t = a[i];
j = i - 1;
while (j >= 0 && t < a[j]) {
a[j + 1] = a[j];
j--;
}
a[j + 1] = t;
}
}
void fill(int a[], size_t len)
{
size_t i;
for (i = 0; i < len; i++) {
a[i] = rand() / (1.0 + RAND_MAX) * 100;
}
}
void print(int a[], size_t len)
{
size_t i;
for (i = 0; i < len; i++) {
if (i) printf(", ");
printf("%d", a[i]);
}
puts("");
}
#define TINY 3
#define MEDIUM 10
#define LARGE 15
int main(void)
{
int tiny[TINY];
int medium[MEDIUM];
int large[LARGE];
srand(time(NULL));
fill(tiny, TINY);
fill(medium, MEDIUM);
fill(large, LARGE);
print(tiny, TINY);
print(medium, MEDIUM);
print(large, LARGE);
sort(tiny, TINY);
sort(medium, MEDIUM);
sort(large, LARGE);
print(tiny, TINY);
print(medium, MEDIUM);
print(large, LARGE);
return 0;
}
I am a complete beginner to stackoverflow and this is my first post. Please forgive if this is not the correct place to post these kinds of queries. I have written code for the Quicksort algorithm, based on the algorithm given in the Algorithms course in Coursera(It is not for any assignments though).
Basically, there are two functions Quicksort which is called recursively and partition() function that returns the index of the pivot. I select the pivot as the first element of the array every time. I checked the partition() function and it works fine but the array is not sorted even after I call the Quicksort() function.
Any help is appreciated. Thanks.
#include <stdio.h>
void swap(int *p, int i, int j)
{
int temp = *(p+i);
*(p+i) = *(p+j);
*(p+j) = temp;
}
int partition(int *q, int l, int r)
{
int i = l+1, j;
int p = l;
int len = r-l +1;
for (j = l+1; j < len; j++)
{
/*printf("%d \n", j);*/
if ( *(q+j) < *(q+p) )
{
swap(q, i, j);
i += 1;
}
}
swap(q, l, i-1);
/*printf("%d", i-1);*/
return (i-1);
}
void quicksort(int *ptr, int low, int high)
{
if (low < high)
{
int p = partition(ptr, low, high);
printf("%d\n", p);
quicksort(ptr, low, p);
quicksort(ptr, p+1, high);
}
}
int main(){
int i;
int a[] = {3, 8, 2, 5, 1, 4, 7, 6};
int len = sizeof(a)/sizeof(a[0]);
for ( i = 0; i < len; ++i)
{
printf("%d ", a[i]);
}
printf("\n");
int *ptr = a;
quicksort(ptr, 0, len-1);
for (i = 0; i < sizeof(a)/sizeof(a[0]); ++i)
{
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
2 corrections.
Small one: Change 3rd line inside if block in QuickSort function
from
quicksort(ptr, low, p);
to
quicksort(ptr, low, p-1);
This will improve performance.
Main error:
Your partition function is wrong. Specifically the loop where j runs from l+1 to r-l+1, because, r-l+1 can be less than l+1
I'll write the partition function for you if you want (post a comment if you face any problem with that) though I'd advice you to do it yourself.
EDIT:
A possible partition function:
int partition(int *q, int l, int r){
int i,j;
int p = *(q + l);
for(i = l + 1, j = r; ;){
while(*(q + i) <= p)
i++;
while(*(q + j) >= p)
j--;
if(i >= j)
break;
swap(q, i, j);
}
return i;
}
Changes noted in comments.
int partition(int *q, int l, int r)
{
int i = l+1, j;
int p = l;
/* fix: int len = r-l+1; is not used */
for (j = l+1; j <= r; j++) /* fix: j <= r */
{
if ( *(q+j) <= *(q+p) ) /* fix: <= */
{
swap(q, i, j);
i += 1;
}
}
swap(q, l, i-1);
return (i-1);
}
void quicksort(int *ptr, int low, int high)
{
if (low < high)
{
int p = partition(ptr, low, high);
quicksort(ptr, low, p-1); /* optimization: p-1 */
quicksort(ptr, p+1, high);
}
}
If interested, Hoare partition scheme is faster. If you switch to this, don't forget to change the two quicksort calls to quicksort(lo, p) and quicksort(p+1, hi) ). You might want to change the Hoare pivot to pivot = A[(lo+hi)/2], which will avoid worst case issue with sorted or reverse sorted array.
http://en.wikipedia.org/wiki/Quicksort#Hoare_partition_scheme