Quick Sort algorithm behaving strangely - c

This is a program which attempts to sort an array using the quick sort algorithm.
All seems to be fine, except that the output is not correct.
(Try the program for n=5, and then n=10. It works correctly for the former, but not the latter.)
#include <stdio.h>
//#include <iostream.h>
//#include <conio.h>
int partition(int arr[], int left, int right) {
int i = left, j = right;
int temp;
//Choosing the middle element as the pivot
//int pivot=arr[left];
int pivot = arr[(left+right)/2];
while (i <= j) {
while (arr[i] < pivot) {i++;}
while (arr[j] > pivot) {j--;}
if (i <= j) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
return i;
}
void quick_sort(int arr[], int p, int r) {
if (p<r) {
int q=partition(arr, p, r);
quick_sort(arr, p, q-1);
quick_sort(arr, q+1, r);
}
}
int main() {
int values[100], n, i;
//clrscr();
printf("Enter no. of elements ");
scanf("%d", &n);
if (n>100) {
printf("Invalid input. Exiting now");
//getch();
return 0;
}
for (i=0; i<100; i++) values[i]=0;
printf("Enter the numbers\n");
for (i=0; i<n; i++) scanf("%d", &values[i]);
printf("The numbers you entered are\n");
for (i=0; i<n; i++) printf("%d ", values[i]);
printf("\n");
quick_sort(values, 0, n-1);
printf("Numbers after sorting are\n");
printf("(The output might not be the expected one (Be careful).\n");
for (i=0; i<n; i++) printf("%d ", values[i]);
//std::cin.get();
return 0;
}

There are two problems. First, the comparison i <= j is wrong. If i == j, you should not swap an element with itself. This should be changed to i < j in both places. Secondly, you should not move the i and j array indicies along after swapping. If it is the last swap, this pushes i past the actual pivot and causes your error.
int partition(int arr[], int left, int right) {
int i = left, j = right;
int temp;
//Choosing the middle element as the pivot
//int pivot=arr[left];
int pivot = arr[(left+right)/2];
while (i < j) {
while (arr[i] < pivot) {i++;}
while (arr[j] > pivot) {j--;}
if (i < j) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
return i;
}

is better to use the std sort from algorithm.h :
http://www.cplusplus.com/reference/algorithm/sort/

Related

endless loop in Quicksort

I was implementing the Quicksort Algorithm, but I have some error and I'm not able to figure out.
I'm using the rand() function to generate random numbers. I'm limiting these numbers in mod(100). mod (100) works well but when I make it mod(10) it doesn't work. The program runs but stops after printing the random unsorted array.
Here's my code:
#include <stdio.h>
#include <stdlib.h>
int a[50];
void quicksort(int l, int r)
{
int s;
if(l<r)
{
s=partition(l, r);
quicksort(l, s-1);
quicksort(s+1, r);
}
}
int partition(int l, int r)
{
int p, i, j, temp;
p = a[l];
i=l;
j=r+1;
while(i<=j)
{
while(a[i]<=p && i<r+1)
i=i+1;
while(a[j]>=p && j>l)
j=j-1;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
temp = a[i];
a[i] = a[j];
a[j] = temp;
temp = a[l];
a[l] = a[j];
a[j] = temp;
return j;
}
int main()
{
int n, i;
printf("Enter number of elements: \n");
scanf("%d", &n);
printf("Random Array: \n");
for(i=0; i<n; i++)
{
a[i] = rand()%100; // The error seems to be here for rand()%10
printf("%d ", a[i]);
}
quicksort(0,n-2);
printf("\n Solution: \n");
for(i=0; i<n; i++)
{
printf("%d ", a[i]);
}
return 0;
}
Any help would be appreciated.
Thanks.
This loop condition inside partition() can end up in an endless loop:
while(i<=j)
To avoid change it to
while(i<j)
It never needs to swap at two identical indexes anyway.

Bubble sort does not seem to work-segmentation error

Hi there somehow my bubble sort that is suppose to work does not seem to work.Im not sure where the error is being caused.It is suppose to give me a sorted output list.It is giving me segmentation error and have been trying this for about 1 hr.Heres the code:
#include <stdio.h>
#include <stdlib.h>
#define N 10
void sort(int [], int);
void show(char *, int [], int);
int main(void)
{
int i, j, a[N];
srand(0);
for (j = 1; j <= 5; j++) {
// initialise array (pseudo-randomly)
for (i = 0; i < N; i++) {
a[i] = rand()%100;
}
// display, sort, then re-display
printf("Test #%d\n",j);
show("Sorting", a, N);
sort(a, N);
show("Sorted ", a, N);
}
return 0;
}
// sort array using bubble sort
void sort(int a[], int n)
{
int i, j, nswaps;
for (i = 0; i < n; i--) {
nswaps = 0;
for (j = n-1; j > i; j--) {
if (a[j] < a[j-1]) {
int tmp;
tmp = a[j];
a[j] = a[j-1];
a[j-1] = tmp;
nswaps++;
}
}
if (nswaps == 1) break;
}
}
// display array, preceded by label
void show(char *label, int a[], int n)
{
int i;
printf("%s:", label);
for (i = 0; i < n; i++) {
printf(" %02d", a[i]);
}
printf("\n");
}
Your are not technically sorting here.Instead of this for (i = 0; i < n; i--), try for (i = 0; i < n; i++).This is because you are starting with i=0 so in a FOR loop you need to increment i.

Why is this program giving a stack overflow?

My C merge code works when I initialize the array globally at the top of the program until the stack overflows. I'm trying to initialize the array with malloc, but when I do, the code will only read in two integers and stop running.
This program pulls random numbers from a file called alg.txt and then sorts them. Again, the code works (up until 500k integers) when defining z at the top of the program to the number of integers to be sorted, and declaring the array globally to be equal to arr[z]. How do I figure out what is going on?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int count = 0;
void merge(int arr[], int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
int L[n1], R[n2];
for (i = 0; i < n1; i++)
L[i] = arr[l + i];
count++;
for (j = 0; j < n2; j++)
R[j] = arr[m + 1+ j];
count++;
i = 0;
j = 0;
k = l;
while (i < n1 && j < n2)
{
if (L[i] <= R[j])
{
arr[k] = L[i];
i++;
count++;
}
else
{
arr[k] = R[j];
j++;
count++;
}
k++;
count++;
}
while (i < n1)
{
arr[k] = L[i];
i++;
k++;
count++;
}
while (j < n2)
{
arr[k] = R[j];
j++;
k++;
count++;
}
}
void mergeSort(int arr[], int l, int r)
{
if (l < r)
{
int m = l+(r-l)/2;
mergeSort(arr, l, m);
mergeSort(arr, m+1, r);
merge(arr, l, m, r);
}
}
void printArray(int A[], int size)
{
int i;
for (i=0; i < size; i++)
printf("%d ", A[i]);
printf("\n");
}
int main()
{
int i;
FILE *myFile;
myFile = fopen("alg.txt", "r");
int z;
printf("Enter the size of the array: ");
scanf("%d", &z);
int *arr = (int *)malloc(z*sizeof(int));
int n = sizeof(arr)/sizeof(arr[0]);
for(i=0; i < z; i++)
{
fscanf(myFile, "%d,", &arr[i]);
}
mergeSort(arr, 0, n - 1);
printf("\nSorted array is \n");
printArray(arr, n);
printf("count is %d\n", count);
return 0;
}
You are declaring the L and R array's locally (inside the merge function). They consume stack on every function call. You should initialize them globally so that they can be stored on the heap. Also, you should declare just one array (like temp_arr in the below code) as there's no need for two separate arrays like L and R.
See Local vs Global variable storage
You can improve your merge function to this:
int temp_arr[500000]; // Global declaration
void merge(int arr[], int l, int m, int r)
{
int i=l, j=m+1, k=l;
while(i<=m && j<=r)
{
if(arr[i]<arr[j])
temp_arr[++k] = arr[++i];
else temp_arr[++k] = arr[++j];
}
while(i<=m)
temp_arr[++k] = arr[++i];
while(j<=r)
temp_arr[++k] = arr[++j];
i = l;
while(i<=r)
arr[i] = temp_arr[++i]; // Storing stored array in arr
}

Quicksorting code doesnt work for more than about ten strings

My code doesn't sort more than ten words and I need it to sort about 2000 strings of alfabet. and string length is less than 20 characters. I made sure that the file read and write is correct. the file have a list of words less than 20 characters and each line contains one word.
the problem is that the quick sort function is not sorting for large amount of strings.
#include <stdio.h>
#include <string.h>
void quickSortMain(char items[][20], int count);
void quickSort(char items[][20], int left, int right);
int main(void)
{
int i=0, n=0;
char str[2000][20];
memset(str, 0 , sizeof(str[0][0])*20*1000);
FILE *fil;
fil=fopen("text.txt","r");
if (fil!=NULL)
{
while (!feof(fil))
{
fgets(str[i], 20, fil);
i++;
}
fclose(fil);
}
else
{
printf("can not open");
scanf("\n");
}
fil=fopen("text.txt","w");
if (fil!=NULL)
{
fclose(fil);
}
else
{
printf("can not open");
scanf("\n");
}
quickSortMain(str, i);
fil=fopen("text.txt","a");
if (fil!=NULL)
{
while(n<i)
{
fprintf(fil,"%s", str[n]);
n++;
}
fclose(fil);
}
else
{
printf("can not open");
scanf("\n");
}
return 0;
}
void quickSortMain(char items[][20], int count)
{
quickSort(items, 0, count-1);
}
void quickSort(char items[][20], int left, int right)
{
int i=left;
int j=right;
char *x=items[(left+right)/2];
char temp[right+1];
while(i <= j)
{
while((strcmp(items[i],x) < 0) && (i < right)) {
i++;
}
while((strcmp(items[j],x) > 0) && (j > left)) {
j--;
}
if(i <= j) {
strcpy(temp, items[i]);
strcpy(items[i], items[j]);
strcpy(items[j], temp);
i++;
j--;
}
}
if(left < j) {
quickSort(items, left, j);
}
if(i < right) {
quickSort(items, i, right);
}
}
The problem is the pivot. When you swap the two elements in the innermost loop:
if(i <= j) {
strcpy(temp, items[i]);
strcpy(items[i], items[j]);
strcpy(items[j], temp);
i++;
j--;
}
one of those two elements, items[i], items[j], might be the pivot. In other words x might be pointing to one of them. After the swap, x isn't pointing to the correct pivot anymore, because the values in the elements to which x is pointing to were changed.
The simplest solution is to allocate additional space for the pivot:
...
char *x=items[(left+right)/2];
char pivot[20];
strcpy(pivot, x);
x = pivot;
...
I have other things to add to 2501's answer.
You should exit program when you detect you cannot read or write the file.
I would use strcpy() rather than memset() to initialize:
for (int n = 0; n < 2000; n++)
{
strcpy(str[n], "");
}
You poorly process newline characters. You should remove them from read lines in your array, and if you don't have one, you should write a warning and skip end of line, and after that add a newline after each word when you write your file. I tested your program and having 20 length lines or a last line with no newline at the end gives bad surprises.
your Quick sort implementation is wrong !!!
Here is a Quicksort for array in C-Programme
#include <stdio.h>
#include <stdlib.h>
int * quickSort(int *A,int pivotIndex, int N);
int partition(int *A, int pivotIndex, int N);
int main(){
int N;
printf("Enter Number of Elements : ");
scanf("%d",&N);
int A[N];
printf("\nEnter Data : ");
int i=0;
for(i=0; i<N; i++)
scanf("%d",&A[i]);
int *p;
p = quickSort(A,0,(N-1));
printf("\nSorted Data : ");
for(i=0; i<N; i++)
printf("%d ",p[i]);
return 0;
}
int * quickSort(int *A, int pivotIndex, int N){
if(pivotIndex < 0 || pivotIndex > N)
return ;
int q = partition(A,pivotIndex, N);
quickSort(A, 0, (q-1));
quickSort(A, (q+1), N);
return A;
}
int partition(int *A, int pivotIndex, int N){
int i = pivotIndex;
int flag = 0;
while(flag == 0){
flag = 1;
int j = N;
int rightFlag = 0, leftFlag = 0;
while(j > i && rightFlag == 0){
if(A[i]>A[j]){
int temp = A[i];
A[i] = A[j];
A[j] = temp;
i = j;
rightFlag = 1;
flag = 0;
}
j--;
}
if(flag == 1)
break;
flag = 1;
j = pivotIndex;
while(j < i && leftFlag == 0){
if(A[i]<A[j]){
int temp = A[i];
A[i] = A[j];
A[j] = temp;
leftFlag = 1;
flag = 0;
i = j;
}
j++;
}
}
return i;
}

C: Sort vector elements in descending order

I am trying to create a function that will rearrange an array so it is in descending order. The array is made up from positive integers, with no two equal elements. This is what I have:
int check (int *v, int n){
int i;
for (i=0; i<n; i++){
if (v[i] != -1){
return -1;
break;
}
else return 1;
}
}
void sortVector (int *v, int n){
int i, k, j=0, vp[n];
while (check(v,n) == -1){
for (i=0; i<n; i++){
for (k=i+1; k<n; k++){
if (v[k] > v[i]) break;
else if (k == n-1){
vp[j] = v[i];
v[i] = -1;
j++;
}
}
}
}
for (i=0; i<n; i++)
v[i] = vp[i];
}
Which is not working correctly. I've been thinking about this for the past week so some pointers would be great. Thanks.
I tried to follow the idea that you have stated in your comment by starting from your code above and made few changes and here is the two final functions
#include <stdio.h>
int check (int *v, int n)
{
int i;
for (i=0; i<n; i++)
{
if (v[i] != -1)
{
return -1; // break is useless because return has the same effect
}
}
return 1; // you need to add a return here to handle all the cases
// the case if the loop is not entered you need to return a value
}
void sortVector (int *v, int n)
{
int i, k, j=0, vp[n];
int maxIndex=0;//you need to add this variable in order to keep track of the maximum value in each iteration
while (check(v,n) == -1)
{
for (i=0; i<n; i++)
{
maxIndex=i; //you suppose that the maximum is the first element in each loop
for (k=i+1; k<n; k++)
{
if (v[k] > v[maxIndex])
maxIndex=k; // if there is another element greater you preserve its index in the variable
}
//after finishing the loop above you have the greatest variable in the array which has the index stored in maxIndex
vp[i] = v[maxIndex]; // put it in vp array
v[maxIndex]=v[i];//put it in treated elements zone
v[i]=-1;// make it -1
j++;
}
}
for (i=0; i<n; i++)
v[i] = vp[i];
}
This is the test
int main()
{
int tab[]= {1,152,24,11,9};
sortVector (tab, 5);
int i=0;
for(i=0; i<5; i++)
{
printf("%d ",tab[i]);
}
return 0;
}
which gives the desired output
152 24 11 9 1
Note: You can improve your code by making swaps on the same array instead of allocating another array !
There are really lots of algorithms for sorting. A simple algorithm is to find the minimum element in your array and put it in the first position by swapping it with whatever item was in the first position and then recursively sorting the array but this time starting at the next position.
void sort(int a[], int l, int r)
{ if(l == r) return; /* 1-elemnt array is already sorted */
int min = l;
for(int i = l+1; i <= r; i++)
{ if(a[i] < a[min])
{ min = i;
}
}
swap(a[l], a[min]);
sort(a, l+1, r);
}
You can also do it iteratively.
Perhaps, the intention like following
int check (int *v, int n){
int i;
for (i=0; i<n; i++){
if (v[i] != -1){
return -1;
//break; //This code that does not reach
}
//else return 1; //move to after for-loop
}
return 1;
}
void ordenaVetor (int *v, int n){
int i, k, j=0, vp[n];
while (check(v,n) == -1){
for (i=0; i<n; i++){
if(v[i]<0) continue;//Element of -1 excluded. v[k] too.
for (k=i+1; k<n; k++){
if (v[k]>=0 && v[i] < v[k]) break;
}
if (k == n){
vp[j] = v[i];
v[i] = -1;
j++;
break;//start over
}
}
}
for (i=0; i<n; i++){
v[i] = vp[i];
}
}
You could use an existing sort implementation instead of reinventing the wheel:
#include <stdlib.h>
int desc(void const *a, void const *b)
{
if ( *(int *)a < *(int *)b ) return 1;
return -1;
}
void sortVector (int *v, int n)
{
qsort(v, n, sizeof *v, desc);
}

Resources