Merge sort in C - c

I am new in programming/C.
I understand the algorithm of merge-sort as an algorithm but when it comes to programming, it appears that I am doing something wrong.
Could anybody help?
Thanks.
Here is my code:
merge(int A[],int p,int q,int r);
part(int A[],int p,int r);
int main()
{
int A [6]={10,5,4,0,11,7}, n,y,z;
y=1; z=sizeof(A)/sizeof(int);
part(A,y,z);
for(n=0;n<z;n++)
printf("%d\n", A[n]);
return 0;
}
part(int A[],int p,int r)
{
if (p<r)
{
int q=(p+r)/2;
part(A,p,q);
part(A,q+1,r);
merge(A,p,q,r);
}
}
merge(int A[],int p,int q,int r)
{
int n1=q-r+1,n2=r-q,L[n1+1],R[n2+1],i,j,k;
L[n1+1]=100000;
R[n2+1]=100000;
for (i=0;i<n1;i++)
L[i]=A[p-1+i];
for (j=0;j<n2;j++)
R[j]=A[q+j];
i=0;j=0;
for (k=0;k<r;k++)
if(L[i]<=R[j])
{
A[k]=L[i];
i++;
}
else
{
A[k]=R[j];
j++;
}
}

Here is your corrected code:
#include<stdio.h>
#include<limits.h>
void merge(int A[],int p,int q,int r);
void part(int A[],int p,int r);
int main()
{
int A [6]={10,5,4,0,11,7}, n,y,z;
y=0; z=6;
part(A,0,z-1); // Pass starting from 0 to Length - 1 of Array
for(n=0;n<z;n++)
printf("%d\n", A[n]);
return 0;
}
void part(int A[],int p,int r)
{
if (p<r)
{
int q=(p+r)/2;
part(A,p,q);
part(A,q+1,r);
merge(A,p,q,r);
}
}
void merge(int A[],int p,int q,int r)
{
int n1=q-p+1,n2=r-q;
int L[n1+1],R[n2+1],i,j,k;
L[n1]=INT_MAX;
R[n2]=INT_MAX;
for (i=0;i<n1;i++)
L[i]=A[p+i];
for (j=0;j<n2;j++)
R[j]=A[q+j+1];
i=0;j=0;
for (k=p;k<=r;k++)
{
if(L[i]<=R[j])
{
A[k]=L[i];
i++;
}
else
{
A[k]=R[j];
j++;
}
}
}
These are the parts which were wrong:
int n1=q-r+1,n2=r-q // --> Your calculation of new indices was wrong
These indices take you out of bounds of the array:
L[n1+1]=100000;
R[n2+1]=100000;
Also instead of using a random value like 100000 use INT_MAX in limits.h for the sentinel element.
for (k=0;k<r;k++) // ->wrong
You should move from left index of array to right not from 0th index.
Output:
0
4
5
7
10
11
Rest you can check for yourself.

Alternative solution with part parameters 0 to size of array. My old C compiler doesn't support variable sized arrays so I used _alloca() as a substitute. Other alternatives would be to pass a second array to be used as a temp array for the merge sort, and either a top down or bottom up merge sort. The copy operations can be avoided in top down by alternating the direction of the merge based on the level of recursion, with a pair of co-recursive functions: the top level would be partAtoA(), which would call partAtoB() (which would call partAtoA(), ...).
#include <stddef.h>
#include <stdio.h>
void merge(int A[],int p,int q,int r);
void part(int A[],int p,int r);
int main()
{
int A[6]={10,5,4,0,11,7}, n,y,z;
y=0;
z=sizeof(A)/sizeof(int);
part(A,y,z);
for(n=0;n<z;n++)
printf("%d\n", A[n]);
return 0;
}
void part(int A[], int p, int r)
{
int q;
if ((r - p) < 2)
return;
q=(p+r)/2;
part(A,p,q);
part(A,q,r);
merge(A,p,q,r);
}
void merge(int A[],int p,int q,int r)
{
int n1=q-p, n2=r-q;
int i,j,k;
/* using _alloca for variable size arrays */
int * L = _alloca(n1*sizeof(int));
int * R = _alloca(n2*sizeof(int));
for (i=0; i<n1; i++)
L[i]=A[p+i];
for (j=0; j<n2; j++)
R[j]=A[q+j];
i=0;j=0;
for(k=p;k<r;k++)
if(j>=n2 || i<n1 && L[i]<=R[j])
A[k]=L[i++];
else
A[k]=R[j++];
}

Related

Quicksort: Why wrong output

I want to sort the given array using quicksort.
So I wrote this code in c for quicksort algorithm but its not giving me correct answer.Its giving me the same output as the input.
eg: If i give input as
3
2
1
then it is giving
Output:
3
2
1
Please help and tell me where is the mistake.
#include<stdio.h>
void quicksort(int a[],int p,int r);
int partition(int a[],int p,int r);
void swap(int a,int b);
int main()
{
int n,i,p,r;
printf("ENter no of elements");
scanf("%d",&n);
int a[n];
printf("ENter the elements");
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
p=1;
r=n;
quicksort(a,1,n);
printf("\n");
for(i=1;i<=n;i++)
{
printf("%d\n",a[i]);
}
return 0;
}
void quicksort(int a[],int p,int r)
{
int q;
if(p<r)
{
q = partition(a,p,r);
quicksort(a,p,q-1);
quicksort(a,q+1,r);
}
}
int partition(int a[],int p,int r)
{
int x,i,j;
x=a[r];
i=p-1;
for(j=p;j<=r-1;j++)
{
if(a[j]<=x)
{
i=i+1;
swap(a[i],a[j]);
}
}
swap(a[i+1],a[r]);
return (i+1);
}
void swap(int a,int b)
{
int t;
t=a;
a=b;
b=t;
}
void swap(int a,int b)
This line is taking the two parameters as copies of the values. The swapping is done on he copies.
void swap(int* a, int* b)
This is the C-style of passing parameters by reference. You need to pass the references then:
swap(&a[i], &a[j]);

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){

C program for quicksort(recursive)

The following c program is a quicksort recursive program. Although I have written this code according to the Cormen explanation, yet it is incorrectly sorting the input.For example it is sorting the input 3,8,1 to 3,1,8. Thanks a lot in advance for finding the mistake
#include<stdio.h>
void printa(int a[],int size)
{
int i;
printf("\n");
for(i=0;i<size;i++)
{
printf("%d\n",a[i]);
}
}
void swap(int *a,int *b)
{
int temp;
temp=*a;
*a=*b;
*b=temp;
}
int partition(int a[],int p,int r)
{
int i,j,x;
i=p-1;
x=a[r];
for(j=p;j<r;j++)
{
if(a[j]<=x)
{
i=i+1;
swap(&a[i],&a[j]);
}
swap(&a[i+1],&a[r]);
}
return i+1;
}
void quicksort(int a[],int p,int r)
{
if(p<r)
{
int q;
q=partition(a,p,r);
quicksort(a,p,q);
quicksort(a,q+1,r);
}
}
main()
{
int a[50],i,size;
printf("enter the size of the array\n");
scanf("%d",&size);
printf("enter the elements of the array\n");
for(i=0;i<size;i++)
{
scanf("%d",&a[i]);
}
quicksort(a,0,size-1);
printa(a,size);
}

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

Selection sort on array in C

I'm trying to create a simple(?) selection sort program in C that selects the largest integer of an integer array and places it in the location a[n-1], places the second largest number in a[n-2], etc until the smallest number is placed in a[0]. I've run through the below code on paper and it seems like it should work, but when I compile it I'm getting faulty results. Am I missing something obvious?
/* The program implements selection sort*/
#include <stdio.h>
#include "simpio.h"
#define n 5
void GetArray(int a[]);
void SelectionSort(int a[]);
int FindMax(int a[], int high);
void swap(int a[], int p1, int p2);
void PrintArray(int a[]);
main()
{
int a[n];
GetArray(a);
SelectionSort(a);
PrintArray(a);
getchar();
}
void GetArray(int a[])
{
int i;
for(i=0;i<n;i++)
{
printf("Enter integer# %d", i+1);
a[i]=GetInteger();
}
}
void SelectionSort(int a[])
{
int i, max;
for(i=0;i<n;i++)
{
max=FindMax(a,i);
swap(a,max,(n-1-i));
}
}
int FindMax(int a[], int high)
{
int i, index;
index=high;
for(i=high;i<n;i++)
{
if(a[i]>a[index])
index=i;
}
return index;
}
void swap(int a[], int p1, int p2)
{
int temp;
temp=a[p2];
a[p2]=a[p1];
a[p1]=temp;
}
void PrintArray(int a[])
{
int i;
for(i=0;i<n;i++)
printf("a[%d]=%d\n", i, a[i]);
}
Change these method to:
void SelectionSort(int a[])
{
int i, max;
for(i=0;i<n;i++)
{
max=FindMax(a,n-i-1);
swap(a,max,n-i-1);
}
}
int FindMax(int a[], int high)
{
int i, index;
index=high;
for(i=0;i<high;i++)
{
if(a[i]>a[index])
index=i;
}
return index;
}
I actually tested my answer and it works.
Selection sort is process of comparing minimum element from the list and placing from the least index.
Now consider below code snippet.
public void selectionSort(int[] elements) {
for(int i=0;i<elements.length;i++) {
int minPosition = i;
for(int j=i+1;j<elements.length;j++) {
if(elements[minPosition]>elements[j])
minPosition = j;
}
int temp = elements[i];
elements[i] = elements[minPosition];
elements[minPosition] = temp;
}
}
Thanks for reading, let me know feedback to improve from myside
Shouldn't:
max=FindMax(a,i);
swap(a,max,(n-1-i));
Be:
max=FindMax(a,i);
swap(a,max,i);
otherwise, next time through the loop, you'll find the same max value in the top position in the array.
A very basic implementation of selection sort
#include<stdio.h>
main()
{
int i,j,n=7,a[]={1,2,5,3,8,9,5},key;
for(j=1;j<n;j++)
{
key=a[j]; //a[j] is the new element to be added to the sorted
//sequence
i=j-1;
while(i>=0 && key<a[i]) //traverse through the sorted sequence
{a[i+1]=a[i];i--;} //until the place of key is found
a[i+1]=key;
}
for (j=0;j<n;j++)
printf("%d",a[j]);
}
#include<stdio.h>
#include<conio.h>
int removex(int arr[],int small,int n)
{
int i=0;
for(;i<n;i++)
if(arr[i]==small) //searching that no to delete
break;
for(;i<n-1;i++)
arr[i]=arr[i+1]; //delete by overloading no
return n-1;
}
void selectSort(int arr[],int sort[],int n)
{
int j=0,k=0,small;
while(n!=0)
{
small=arr[0];
for(j=0;j<n;j++)
if(arr[j]<small)
small=arr[j]; //finding smallest no
sort[k++]=small;
n=removex(arr,small,n); //removing that from list as we included that no into sorted list
}
}
void main()
{
int arr[10],arr2[10],i,n;
clrscr();
printf("Enter how many elements");
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&arr[i]);
selectSort(arr,arr2,n);
printf("sorted list is\n");
for(i=0;i<n;i++)
printf("%d\n",arr2[i]);
getch();
}

Resources