Quick Sort Algorithm realisation - c

i've already sought information for the quick-sort algorithm. But i still can not realize it on C. I'm trying but the Quicksort function doesn't work at all. I Can't find errors in my code. Please, help me to understand what's going on.
#include <stdio.h>
#include <stdlib.h>
void swap(int a, int b)
{
int temp = 0;
temp = a;
a = b;
b = temp;
}
int Partition(int p , int r, int A[r - p + 1])
{
int j = 0;
int x = A[r - 1];
int i = p - 1;
for(j = p - 1; j < r - 1; j++) {
if(A[j] <= x) {
i = i + 1;
swap(A[i], A[j]);
}
}
swap(A[i], A[r - 1]);
return i + 1;
}
void Quicksort(int p, int r, int A[r - p + 1])
{
int q = 0;
if((p - 1) < (r - 1)) {
q = Partition(p ,r , A);
Quicksort(p, q - 1, A);
Quicksort(q + 1, r, A);
}
}
int main(int argc, char *argv[])
{
int A[] = {10, 5, 1, 3, 9, 2, 4, 8, 7, 6};
int i = 0;
int length = sizeof(A) / sizeof(int);
Quicksort(1, length , A);
for(i = 0; i < length; i ++) {
printf("%d ", A[i]);
}
printf("\n");
return 0;
}

You have to pass the values as pointers to the swap function
void swap(int *a, int *b)
{
int temp = 0;
temp = *a;
*a = *b;
*b = temp;
}
and then change
swap(A[i], A[j]);
to
swap(&A[i], &A[j]);
and
swap(A[i], A[r - 1]);
to
swap(&A[i], &A[r - 1]);

Related

Top-down merge sorting. Merge method abstract exchange method

What is the problem? Why is there always a fixed value of comparisons and swaps? And am I correct in counting swaps and comparisons in principle? I mean, do I accidentally count them in the wrong places? Maybe in some places it is not necessary to do this? Please help me because I really can't figure out what's wrong
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void mergeAbstract(int *a, int lb, int split, int ub, int *count, int *swaps)
{
int size = ub - lb + 1;
int *sub = (int *)malloc((ub + 1) * sizeof(int));
int i = 0, j = size - 1, k = lb;
int s;
for (s = 0; s < split + 1 - lb; s++) sub[s] = a[lb + s];
for (s = split + 1 - lb; s < size; s++) sub[s] = a[ub - (s - (split + 1 -lb))];
while (i <= j) {
(*count) += 2;
if (sub[i] > sub[j]) {
(*swaps)++;
a[k] = sub[j];
j--;
} else {
(*swaps)++;
a[k] = sub[i];
i++;
}
k++;
}
(*count)++;
free(sub);
}
void mergeSort(int *a, int lb, int ub, int *count, int *swaps) {
long split;
if (lb < ub) {
split = (lb + ub) / 2;
mergeSort(a, lb, split, count, swaps);
mergeSort(a, split + 1, ub, count, swaps);
mergeAbstract(a, lb, split, ub, count, swaps);
}
}
void arrprint(int *arr, int n) {
printf("%d", *arr);
int i;
for (i = 1; i < n; i++) printf(" %d", arr[i]);
puts("");
}
int main(int argc, char *argv[]) {
int n = 10;
int *arr = NULL;
arr = (int *)malloc(n * sizeof *arr);
int c = 0;
int *count = &c;
int h = 0;
int *swaps = &h;
srand(time(NULL));
int s;
for (s = 0; s < n; s++)
arr[s] = rand() % 50;
arrprint(arr, n);
mergeSort(arr, 0, n - 1, count, swaps);
arrprint(arr, n);
free(arr);
puts("");
printf("Comparison ans swaps : %d %d\n", *count ,*swaps);
return 0;
}

C.Heapsort .Count the number of swaps and comparisons

The sorting seems to be working correctly. At least it sorts correctly :) It remains only to count the number of comparisons and swaps. How to calculate and output it?Somehow stalled at this point.. I will be very grateful for your help.If you demonstrate it with the updated code , I will be doubly grateful.
#include <stdio.h>
#include <stdlib.h>
void keyDown(int* arr, int n, int head)
{
int j;
if(2*head + 2 < n && arr[2*head + 1] < arr[2*head + 2])
{
j = 2*head + 2;
}
else j = 2*head + 1;
while(arr[head] < arr[j] && head < n / 2)
{
int tmp = arr[head];
arr[head] = arr[j];
arr[j] = tmp;
head = j;
if(2*head + 2 < n && arr[2*head + 1] < arr[2*head + 2])
{
j = 2*head + 2;
}
else j = 2*head + 1;
}
}
void heapSort(int* arr, int n)
{
int i;
for(i = n/2 - 1; i >= 0; i--)
{
keyDown(arr,n,i);
}
int l = n;
while(l > 1)
{
l--;
int tmp = arr[l];
arr[l] = arr[0];
arr[0] = tmp;
keyDown(arr,l,0);
}
}
int main(int argc, char *argv[]) {
int n=10;
int start, end,i;
int *arr;
arr=(int *)malloc(n*sizeof(int));
time_t invocation_time = time(NULL);
srand(invocation_time);
int s;
for (s=0;s<n;s++)
{
arr[s] = rand() % 50;
printf ("%d \n", arr[s]);
}
printf ("\n");
heapSort(arr, n);
for (i=0;i<n;i++){
printf ("%d \n", arr[i]);
}
return 0;
}
count the number of comparisons and swaps
make functions
//global counters
unsigned comparisons = 0, swaps = 0;
int lessthan(int a, int b) {
comparisons++;
return (a < b);
}
void swap(int *a, int *b) {
swaps++;
int tmp = *a; *a = *b; *b = tmp;
}
and then replace comparisons and swaps in your existing code with the specific function you need.
int main(int argc, char **argc) {
//...
if (lessthan(a[i], a[j])) swap(a+i, a+j);
//...
printf("comparisons: %u; swaps: %u\n", comparisons, swaps);
}

Why variable "q" in quick-sort function equals 7 after first procedure (call)

I have implemented quicksort algorithm in C but I don't know how q and r work in quick_sort function. When the partitioning function returns i which is 1 it assigns this value to q but then for some reason, q becomes 7 and r becomes 0.
int partitioning(int A[10], int p, int r);
void quick_sort(int A[10], int p, int r);
int main() {
int A[10] = { 8, 7, 0, 20, 60, 5, 3, 7, 45, 1}, i;
for (i = 0; i <= 9; i++) {
printf(" %d ", A[i]);
}
printf("\n\nFinal Array\n\n");
quick_sort(A, 0, 9);
for (i = 0; i <= 9; i++) {
printf(" %d ", A[i]);
}
return 0;
}
int partitioning(int A[10], int p, int r) {
int tmp, i, x, j;
x = A[r];
i = p - 1;
for (j = p; j <= r; j++) {
if (A[j] < x) {
i++;
tmp = A[i];
A[i] = A[j];
A[j] = tmp;
}
}
i++;
tmp = A[i];
A[i] = A[r];
A[r] = tmp;
return i;
}
void quick_sort(int A[10], int p, int r) {
int q;
printf("%d\n", q);
if (p < r) {
q = partitioning(A, p, r);
quick_sort(A, p, q - 1);
quick_sort(A, q + 1, r);
}
}

Writing Merge Sort Pseudo-Code Procedure in C

I have been going through Introduction to Algorithms, and have been trying to implement the MERGE-SORT algorithm in C programming language to gain a better understanding of it.
The book presents two pseudo-codes:
and
While I do understand the above procedures, I must be missing something during the implementation.
I must be missing something from the pseudo-code but cannot figure it out yet. Any suggestions as to why this is happening would be appreciated.
EDIT: Updated Code and Output
/* C program for Merge Sort */
#include<stdlib.h>
#include<stdio.h>
void MERGE(int [], int , int , int );
void printArray(int [], int );
void MERGE_SORT(int [], int , int );
int main(void)
{
int A[] = { 12, 11, 13, 5, 6, 7, 2, 9 };
int arr_size = sizeof(A) / sizeof(A[0]);
printf("Given array is \n");
printArray(A, arr_size);
MERGE_SORT(A, 0, arr_size); //Fixed: Index to start from zero
printf("\nSorted array is \n");
printArray(A, arr_size);
return 0;
}
void MERGE(int A[], int p, int q, int r)
{
int i = 0;
int j = 0;
int n1 = q - p + 1; //Computing length of sub-array 1
int n2 = r - q; //Computing length of sub-array 2
int *L = malloc((n1 + 2) * sizeof(*L + 1)); //Creating Left array
int *R = malloc((n2 + 2) * sizeof(*R + 1)); //Creating Right array
for (int i = 0; i <= n1; i++) { //Fixed: <=, i start from 0
L[i] = A[p + i - 1];
}
for (int j = 0; j <= n2; j++) { //Fixed: <=, i start from 0
R[j] = A[q + j];
}
L[n1 + 1] = 99; //Placing Sentinel at the end of array
R[n2 + 1] = 99;
i = 1;
j = 1;
/*Prior to the first iteration k = p, so the subarray is empty.
Both L[i] and R[j] are the smallest elements of their arrays and have not
been copied back to A*/
for (int k = p; k <= r; k++) { //Fixed: <=
if (L[i] <= R[j]) {
A[k] = L[i];
i++;
}
else { //Fixed: Assignment and not condition check for A[k]
A[k] = R[j];
j++;
}
}
free(L);
free(R);
}
void MERGE_SORT(int A[], int p, int r)
{
//During first iteration p = 1 & r = 8
if (p < r) {
int q = (p + r) / 2;
MERGE_SORT(A, p, q);
MERGE_SORT(A, q + 1, r);
MERGE(A, p, q, r);
}
}
/* Function to print an array */
void printArray(int Arr[], int size)
{
int i;
for (i = 0; i < size; i++)
printf("%d ", Arr[i]);
printf("\n");
}
Looked in the pseudo code and found out that some things have been mistakenly written wrong.
1. You need to be careful with the array index to start from 0 or 1
2. Merge last part in for loop is actually an assignment instead for conditional check.
Edit: Have updated the code to fix for the error Stack around the variable A was corrupted
Please find the corrected code here(Lookout for //Fixed for fixes)
/* C program for Merge Sort */
#include<stdlib.h>
#include<stdio.h>
void MERGE(A, p, q, r);
void printArray(Arr, size);
void MERGE_SORT(A, p, r);
int main(void)
{
int A[] = { 12, 11, 13, 5, 6, 7, 2, 9 };
int arr_size = sizeof(A) / sizeof(A[0]);
printf("Given array is \n");
printArray(A, arr_size);
MERGE_SORT(A, 0, arr_size - 1); //Fixed: Index to start from zero, arr_size - 1
printf("\nSorted array is \n");
printArray(A, arr_size);
return 0;
}
void MERGE(int A[], int p, int q, int r)
{
int i = 0;
int j = 0;
int n1 = q - p + 1; //Computing length of sub-array 1
int n2 = r - q; //Computing length of sub-array 2
int *L = malloc((n1+1) * sizeof(*L+1)); //Creating Left array
int *R = malloc((n2+1) * sizeof(*R+1)); //Creating Right array
for (int i = 0; i < n1; i++) { //Fixed: i start from 0
L[i] = A[p + i];
}
// int arr_size = sizeof(A) / sizeof(A[0]);
for (int j = 0; j < n2; j++) { //Fixed: j start from 0
R[j] = A[q + j + 1];
}
L[n1] = 99; //Placing Sentinel at the end of array
R[n2] = 99;
i = 0; //Fixed: i and j to start from 0
j = 0;
/*Prior to the first iteration k = p, so the subarray is empty.
Both L[i] and R[j] are the smallest elements of their arrays and have not
been copied back to A*/
for (int k = p; k <= r; k++) { //Fixed: <=
if (L[i] <= R[j]) {
A[k] = L[i];
i++;
}
else { //Fixed: Assignment and not condition check for A[k]
A[k] = R[j];
j++;
}
}
free(L);
free(R);
}
void MERGE_SORT(int A[], int p, int r)
{
//During first iteration p = 1 & r = 8
if (p < r) {
int q = (p + r) / 2;
MERGE_SORT(A, p, q);
MERGE_SORT(A, q + 1, r);
MERGE(A, p, q, r);
}
}
/* Function to print an array */
void printArray(int Arr[], int size)
{
int i;
for (i = 0; i < size; i++)
printf("%d ", Arr[i]);
printf("\n", size);
}
Hope it helps.
Revert for any doubts.
here are some changes i have done to your code `
#include<stdlib.h>
#include<stdio.h>
void MERGE(int *A,int p,int q,int r);
void printArray(int *Arr,int size);
void MERGE_SORT(int *A,int p,int r);
int main(void){
int A[] = { 12, 11, 13, 5, 6, 7, 2, 9 };
int arr_size = sizeof(A) / sizeof(A[0]);
printf("Given array is \n");
printArray(A, arr_size);
MERGE_SORT(A, 0, arr_size -1); // pass the indices of the array
printf("\nSorted array is \n");
printArray(A, arr_size);
return 0;
}
void MERGE(int A[], int p, int q, int r){
int i = 0;
int j = 0;
int k; //declair it here
int n1 = q - p + 1; //Computing length of sub-array 1
int n2 = r - q; //Computing length of sub-array 2
int *L = malloc((n1) * sizeof(*L+1)); //Creating Left array
int *R = malloc((n2) * sizeof(*R+1)); //Creating Right array
for (int i = 0; i < n1; i++) { //start coping from zero
L[i] = A[p + i];
}
for (int j = 0; j < n2; j++) {
R[j] = A[q +1 + j];
}
// L[n1] = 99; we won't be needing these as to mark the end we already know the size of arrays
// R[n2] = 99;
// i = 1;
// j = 1;
/*Prior to the first iteration k = p, so the subarray is empty.
Both L[i] and R[j] are the smallest elements of their arrays and have not
been copied back to A*/
for (k = p; k < r+1 && i < n1 && j<n2; k++) {
//i & j checks weather the array has completed or not
if (L[i] <= R[j]) {
A[k] = L[i];
i++;
}
else {
A[k]=R[j];
j++;
}
}
// when one of the array is empty u can copy the rest of the array with out compairing
while(i<n1)
A[k++]=L[i++];
while(j<n2)
A[k++]=R[j++];
free(L);
free(R);
}
void MERGE_SORT(int A[], int p, int r)
{
//During first iteration p = 1 & r = 8
if (p < r) {
int q = (p + r) / 2;
MERGE_SORT(A, p, q);
MERGE_SORT(A, q + 1, r);
MERGE(A, p, q, r);
}
}
/* Function to print an array */
void printArray(int Arr[], int size){
int i;
for (i = 0; i < size; i++)
printf("%d ", Arr[i]);
printf("\n");
}`
first of all you were not passing the right parameters to the function.
then the concept of using infinity to indicate is not good as one can want to sort bigger number than that in that case you would have to increase infinity an alternative approach is given above.
Mean while i also solved the problem with your code here it was again with the array index were not rightly used check it out now its working:`
#include<stdlib.h>
#include<stdio.h>
void MERGE(A, p, q, r);
void printArray(Arr, size);
void MERGE_SORT(A, p, r);
int main(void)
{
int A[] = { 12, 11, 13, 5, 6, 7, 2, 9 };
int arr_size = sizeof(A) / sizeof(A[0]);
printf("Given array is \n");
printArray(A, arr_size);
MERGE_SORT(A, 1, arr_size);
printf("\nSorted array is \n");
printArray(A, arr_size);
return 0;
}
void MERGE(int A[], int p, int q, int r)
{
int i = 0;
int j = 0;
int n1 = q - p + 1; //Computing length of sub-array 1
int n2 = r - q; //Computing length of sub-array 2
int *L = malloc((n1+1) * sizeof(*L+1)); //Creating Left array
int *R = malloc((n2+1) * sizeof(*R+1)); //Creating Right array
for (int i = 1; i < n1; i++) {
L[i] = A[p + i - 1];
}
for (int j = 1; j < n2; j++) {
R[j] = A[q + j];
}
L[n1] = 99; //Placing Sentinel at the end of array
R[n2] = 99;
i = 1;
j = 1;
/*Prior to the first iteration k = p, so the subarray is empty.
Both L[i] and R[j] are the smallest elements of their arrays and have not
been copied back to A*/
for (int k = p; k < r; k++) {
if (L[i] <= R[j]) {
A[k] = L[i];
i++;
}
else if (A[k] == L[i])
j++;
}
free(L);
free(R);
}
void MERGE_SORT(int A[], int p, int r)
{
//During first iteration p = 1 & r = 8
if (p < r) {
int q = (p + r) / 2;
MERGE_SORT(A, p, q);
MERGE_SORT(A, q + 1, r);
MERGE(A, p, q, r);
}
}
/* Function to print an array */
void printArray(int Arr[], int size)
{
int i;
for (i = 0; i < size; i++)
printf("%d ", Arr[i]);
printf("\n");
}

How to debug segmentation fault in C for the following code..I have used malloc and free in many functions as well as main

Basically this is a C code for Oil Well challenge from hackerrank website (https://www.hackerrank.com/challenges/oil-well). I am getting segmentation fault or abort called when I submit this code.(It is working sometime in my system compiler).
Can someone tell me how to rectify this problem?. Thanks in advance.
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>
int *min, c, r, q = 0;
void findmin()
{
int i, minimum = min[0];
for (i = 0; i < q; i++)
{
if (min[i] > minimum)
minimum = min[i];
}
printf("%d", minimum);
}
void calculate(int a[], int r)
{
int sum = 0;
int i;
int *x, *y;
x = (int *) malloc(sizeof(int) * 3);
y = (int *) malloc(sizeof(int) * 3);
for (i = 0; i <= r; i++)
{
x[i] = a[i] % c;
y[i] = a[i] / c;
}
for (i = 1; i <= r; i++)
{
if ((x[i] - x[i - 1]) > (y[i] - y[i - 1]))
sum = sum + (x[i] - x[i - 1]);
else
sum = sum + (y[i] - y[i - 1]);
}
min[q] = sum;
q++;
free(x);
free(y);
}
void swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
void permute(int a[], int l, int r)
{
int i;
if (l == r)
{
for (i = 0; i <= r; i++)
calculate(a, r);
}
else
{
for (i = l; i <= r; i++)
{
swap((a + l), (a + i));
permute(a, l + 1, r);
swap((a + l), (a + i));
}
}
}
int main(void)
{
int i, j, k = 0;
scanf("%d%d", &r, &c);
int *arr;
arr = (int *) malloc(sizeof(int) * r * c);
int **x = (int **) malloc(r * sizeof(int *));
for (i = 0; i < r; i++)
x[i] = (int *) malloc(c * sizeof(int));
for (i = 0; i < r; i++)
for (j = 0; j < c; j++)
scanf("%d", &x[i][j]);
for (i = 0; i < r; i++)
{
for (j = 0; j < c; j++)
{
if (x[i][j] == 1)
{
arr[k] = c * i + j;
k++;
}
}
}
/*printf("Content of arr array is:\n");
for(i=0;i<k;i++)
printf("%d \n",arr[i]);
*/
min = (int *) malloc(sizeof(int) * r * c);
permute(arr, 0, k - 1);
findmin();
free(arr);
free(x);
free(min);
}
Updated code(With all the suggestions and answers taken into account )
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>
int *min,c,r,q=0;
void findmin()
{
int i,minimum=min[0];
/*printf("\nmin array is \n");
for(i=0;i<q;i++)
{
printf("%d ",min[i]);
}*/
for(i=0;i<q;i++)
{
if(min[i]<minimum)
minimum=min[i];
}
printf("%d",minimum);
}
void calculate(int a[],int r)
{
int sum=0;
int i;
int *x,*y;
x = (int *)malloc(sizeof(int)*r+1);
y = (int *)malloc(sizeof(int)*r+1);
for(i=0;i<=r;i++)
{
x[i]=a[i]%c;
y[i]=a[i]/c;
}
for(i=1;i<=r;i++)
{
if(abs(x[i]-x[i-1])>abs(y[i]-y[i-1]))
sum=sum+abs(x[i]-x[i-1]);
else
sum=sum+abs(y[i]-y[i-1]);
}
min[q]=sum;
q++;
free(x);
free(y);
//printf("I am here also");
}
void swap(int *x,int *y)
{
int temp;
temp=*x;
*x=*y;
*y=temp;
}
void permute(int a[],int l,int r)
{
int i;
if(l==r)
{
for(i=0;i<=r;i++)
//printf("%d ",a[i]);
calculate(a,r);
//printf("\n");
}
else
{
for(i=l;i<=r;i++)
{
swap((a+l),(a+i));
permute(a,l+1,r);
swap((a+l),(a+i));
}
}
}
int main(){
int i,j,k=0;
scanf("%d%d",&r,&c);
int *arr;
arr = (int *)malloc(sizeof(int)*r*c);
int **x = (int **)malloc(r * sizeof(int *));
for (i=0; i<r; i++)
x[i] = (int *)malloc(c * sizeof(int));
for(i=0;i<r;i++)
for(j=0;j<c;j++)
scanf("%d",&x[i][j]);
/*for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
printf("%d ",x[i][j]);
printf("\n");
}*/
for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
{
if(x[i][j]==1)
{
arr[k]=c*i+j;
k++;
}
}
}
//printf("Content of arr array is:\n");
//for(i=0;i<k;i++)
//printf("%d \n",arr[i]);
//printf("\nCalling permutation\n");
min = (int *)malloc(sizeof(int)*r*c);
permute(arr,0,k-1);
//printf("\nFinding min call\n");
findmin();
free(arr);
for (i = 0; i < r; i++)
{
free(x[i]);
}
free(x);
free(min);
return 0;
}
Here do *(r+1) rather than *3
x = (int *)malloc(sizeof(int)*3);
y = (int *)malloc(sizeof(int)*3);
Change min[i] > minimum to min[i] < minimum
free all the memory you've allocated i.e. from x[0] to x[r] and y[0] to y[r].
Other than this you're probably all good.
You are allocating (r * sizeof (int)) + 1 bytes,
x = (int *)malloc(sizeof(int)*r+1);
y = (int *)malloc(sizeof(int)*r+1);
but your loop accesses r+1 int objects:
for(i=0;i<=r;i++)
{
x[i]=a[i]%c;
y[i]=a[i]/c;
}
Correct the behaviour based on whatever your intent is - I suspect you want to allocate (r + 1) * sizeof (int) bytes.

Resources