Infinite computation of qsort - c++

i am realsing qsort algorithm, according on Korman. But there is infinite computation, when i trying to start it. I suppose, that problem is in partition. My programms reads from file, first number in file-line is counting of numbers to sort, and next go all numbers
#include <stdio.h>
#include <stdlib.h>
int swap(int &a, int &b);
int sorting(int *array, int &b, int &l);
int partition(int *array ,int &begin, int &last);
int main()
{
FILE* pFile=fopen("input.txt", "r");
//fopen("input.txt", "r");
//fopen("output.txt", "w");
int n;
int begin=0;
fscanf(pFile, "%d", &n);
int* array=(int*)malloc(n*sizeof(int));
for (int i=0; i<n; ++i)
fscanf(pFile,"%d", &array[i]);
int n1=n-1;
sorting(array, begin, n1);
printf("JJJJ");
for (int i=0; i<n; ++i)
printf("%d ", array[i]);
printf("\n");
fclose(pFile);
free(array);
return 0;
}
int sorting(int* array, int &b, int &l)
{
int pivot,pivot1;
if(b<l)
{
pivot=partition(array, b, l);
printf("MAXMAX321");
int a=pivot-1;
sorting(array, b, a);
printf("MAXMAX123");
pivot1=pivot+1;
sorting(array, pivot1, l);
printf("MAXMAX");
}
return 0;
}
int partition(int* array, int &b, int &l)
{
int x=array[b];
int i=b;
int j=l;
while(true)
{
while(array[j]>x){
printf("AHAH");
--j;
}
while(array[i]<x){
printf("AZAZA");
++i;
}
if(i<j)
swap(array[i],array[j]);
else
return j;
}
}
int swap(int &x, int &y)
{
x=x+y;
y=x-y;
x=x-y;
return 0;
}
Thank you in advance.

This part is very dangerous code:
while(true)
{
while(array[j]>x){
printf("AHAH");
--j;
}
while(array[i]<x){
printf("AZAZA");
++i;
}
if(i<j)
swap(array[i],array[j]);
else
return j;
}
Avoid while (true) as much as possible, except on very special case you should have a clear condition stated in the loop. Here it is the one that leads to `return. It will clarify the goal of the loop.
When testing array value like while(array[i]<x) compare i to the array size before ! You're never sure that you condition will always be met in the array, ensure you have a safety belt.

I cannot understand what you are doing in function partition but doing it like this should work:
int partition(int* array, int &b, int &l)
{
int pivot_index = l;//You can take here everything between b and l
//swap(array[l], array[pivot_index]); decomment this if your pivot is between b and l
int current_pos = b;
for(int i = b;i < l - 1; ++i)
if(array[i] <= array[pivot_index])
swap(array[i], array[current_pos++]);
swap(array[l], array[current_pos]);
return current_pos;
}

Related

Memory issue implementing quick sort

I am trying to implement quick sort to sort a sequence of integers.
I am getting a segmentation default with the following code:
I implemented partition and quick sort recursive calls.But for some c++ reason I am getting an access to memory or an infinite loop I cant understand why.
#include <fstream>
#include<vector>
#include<iostream>
using namespace std;
int pivotSelection(vector<int> A){
return 0;
}
int partition(vector<int> &A,int l,int r){
int i=l+1;
int p = A[l];
for(int j=0; j< A.size(); j++) {
if(A[j]<p){
swap(A[j], A[i] );
i=i+1;
}
}
swap(A[l], A[i-1]);
return i;
}
vector<int> readArray(char* file){
ifstream inFile;
vector<int> A;
inFile.open(file);
int x;
while (inFile >>x ) {
A.push_back(x);
}
return A;
}
void quickSort(vector<int> &A, int l,int r){
if(r==1) {
return ;
}
if(r>l){
int p= partition(A,l,r);
quickSort(A,l,p-1);
quickSort(A,p+1,r);
}
}
int main(){
vector<int> A;//= readArray((char*)"/home/brunoeducsantos/AlgorithmFoundation/quicksort/data.txt");
A.push_back(3);
A.push_back(5);
A.push_back(7);
A.push_back(1);
int length = A.size();
quickSort(A,0,length-1);
for(int i=0;i<length;i++) cout<<A[i]<<endl;
return 0;
};
The expected result is: 1 3 5 7
Fixes noted in comments:
int partition(vector<int> &A,int l,int r){
int i=l+1;
int p = A[l];
for(int j=i; j<=r; j++) { // fix
if(A[j]<p){
swap(A[j], A[i] );
i=i+1;
}
}
swap(A[l], A[i-1]);
return i-1; // fix
}

Merging two arrays in ascending order

I know the logic how to merge two arrays but the problem is how to code.
This was my code n it is giving correct ans but my sir told me that do it again,please tell me what I have to add in this code,
#include<iostream>
using namespace std;
int mergeArrays(int array1[],int size1,int array2[],int size2);
int main()
{
const int size1=8;
const int size=12;
int arrayA[size1]={10,25,37,49,50,51,55,60};
int arrayB[size]={2,5,26,27,29,32,40,45,70,80,90,95};
mergeArrays(arrayA,size1,arrayB,size);
}
int mergeArrays(int array1[],int size1,int array2[],int size2)
{
int size3=size1+size2;
int *array3=new int[size3];
int k=0;
for(int i=0;i<size1;i++)
{
array3[k]=array1[i];
cout<<" "<<array3[k];
}
int j=0;
for(int i=size1;i<size2;i++)
{
array3[k]=array2[j];
}
for(int i=size1;i<size2;i++)
{
for(int j=0;j<size2;j++)
{
array3[i]=array2[j];
cout<<" "<<array3[i];
}
cout<<endl;
delete[]array3;
return array3[k++];
}
}
I had searched this in many places but could not corrected my code
I had written this code but it is not giving correct ans.
#include<iostream>
using namespace std;
int merge(int *a,int *b,int aSize,int bSize);
int main()
{
const int aSize={8};
const int bSize={12};
int arrayA[aSize]={10,25,37,49,50,51,55,60};
int arrayB[bSize]={2,5,26,27,29,32,40,45,70,80,90,95};
merge(arrayA,arrayB,aSize,bSize);
return 0;
}
int merge(int *a,int *b,int aSize ,int bSize)
{
int cSize=aSize+bSize;
int *c=new int[cSize];
int j=0,k=0;
int i=0;
while(i<=aSize&&j<=bSize )
{
if(a[aSize ]<=b[bSize])
{
c[k]=a[aSize];
k++;
i++;
}
else
{
c[k]=b[bSize];
k++;
j++;
}
}
for(int i=0;i<k;i++)
{
cout<<c[i]<<endl;
}
delete[]c;
return c[k++];
}
your sir request you do Merging two arrays in ascending order. so i think you should return a new array, fill with array1 and array2's element, and the elements should be ascending order. here is a implement.(suppose your input arraies is already in ascending order.)
#include <iostream>
using namespace std;
int mergeArrays(int array1[],int size1,int array2[],int size2, int outArray[]);
int main()
{
const int size1=8;
const int size=12;
int arrayA[size1]={10,25,37,49,50,51,55,60};
int arrayB[size]={2,5,26,27,29,32,40,45,70,80,90,95};
int outArray[size1+size];
int len = mergeArrays(arrayA,size1,arrayB,size, outArray);
cout <<" "<< len;
for (int i = 0; i< size1+size; ++i){
cout <<" " << outArray[i];
}
}
int mergeArrays(int array1[], int size1, int array2[], int size2, int outArray[])
{
int i=0, j=0, k=0;
int retSize = size1+size2;
while (k<retSize){
if (i==size1){// only left array2, copy it
for (; j<size2; ++j){
outArray[k++] = array2[j];
}
}else if (j == size2) { // only left array1, copy it
for (; i<size1; ++i){
outArray[k++] = array1[i];
}
}
else if (array1[i] > array2[j]){ // copy the min value to outArray
outArray[k++] = array2[j++];
}else{
outArray[k++] = array1[i++];
}
}
return k;
}
now, let's look at your first code:
int mergeArrays(int array1[],int size1,int array2[],int size2)
{
int size3=size1+size2;
int *array3=new int[size3];
int k=0;
for(int i=0;i<size1;i++)
{
array3[k]=array1[i]; // k is not changed, so you just assign array1's each value to array3[0]
cout<<" "<<array3[k];
}
int j=0;
// what's the purpose of this loop?
// and in loop, you don't use i, you just repeat set array3[0] = array2[0]!!
for(int i=size1;i<size2;i++)
{
array3[k]=array2[j];
}
for(int i=size1;i<size2;i++) // if array2's length bigger than array1's, will enter this loop.
{
for(int j=0;j<size2;j++)
{
array3[i]=array2[j]; // this just repeat assign array2's each value to array3[i]!!
cout<<" "<<array3[i];
}
cout<<endl;
delete[]array3;
return array3[k++]; // you delete array3, but at here you access it!! this will crash!
// also, in this for i loop, you have return, so it will only execute once.
}
// reach function end and no return if not enter for loop.
}
I haven't looked at your second code. I think you still need to do more study.

Multiplying 2 matrices using pointers

so I am trying to figure out how to multiply 2 matrices using pointers. It successfully works the way it is now, but instead of using conventional array access methods, I would like to learn the use of pointers.
Here is my code:
#include <stdio.h>
#include<conio.h>
#include <stdlib.h>
#include <iostream>
/* Routines called. */
int loadMatrixFromFile(char *filename, int *data);
void showMatrix(int *data, int len);
int makeIdent(int matrixB[5][5], int length);
int matrixA[5][5];
int matrixB[5][5];
int matrixC[5][5];
void multiplyMatrices(int matrixA[5][5], int matrixB[5][5],int matrixC[5][5]);
int main(){
int len, data[1000];
len = loadMatrixFromFile("Numbers.txt", data);
showMatrix(data, len);
makeIdent(matrixB,len);
multiplyMatrices(matrixA, matrixB, matrixC);
}
int makeIdent(int matrixB[5][5], int len){
int i,j;
printf("Matrix B is: \n");
for(i=0;i<5;i++){
for(j=0;j<5;j++){
if(i==j){
matrixB[i][j]=1;
printf("%d ",matrixB[i][j]);
}
else{
matrixB[i][j]=0;
printf("%d ",matrixB[i][j]);
}
}
printf("\n");
}
return matrixB[i][j];
printf("\n");
}
int loadMatrixFromFile(char *filename, int *data){
FILE *in;
int len;
int j;
in = fopen(filename, "r");
if (in == NULL) {
printf("Could not find file: %s \n", filename);
}
else {
printf("Reading numbers...\n");
fscanf(in, "%d", &len);
printf("reading %d numbers from file %s ....\n", len, filename);
for(j=0;j<len;j++) {
fscanf(in, "%d", data + j);
}
fclose(in);
}
for(int i = 0; i<5; i++){
for(int j = 0; j < 5; j++){
matrixA[i][j] = *(data + i*5 + j);
}
}
return len;
}
void showMatrix(int *data, int len){
int j;
int count = 0;
printf("Showing %d numbers from data array....\n", len);
printf("Matrix A is: \n");
for(j=0;j<len;j++) {
printf("%d ", *(data + j));
count++;
if(count % 5 == 0){
printf("\n");
}
}
printf("\n");
}
void multiplyMatrices(int matrixA[5][5], int matrixB[5][5],int matrixC[5][5]){
int i, n, j;
int count = 0;
printf("\n");
printf("Matrix A x Matrix B is: \n");
for (i = 0; i<5; i++){
for (j = 0; j<5; j++){
matrixC[i][j] = 0;
matrixC[i][j] += matrixA[i][j]*matrixB[i][j];
printf("%d ",matrixC[i][j]);
count++;
if(count % 5 == 0){
printf("\n");
}
}
}
}
Well your algorithm for matrix multiplication is completely wrong.
You say 'I want to learn how to do it with pointers', but here's the thing, you're already are doing it with pointers.
In this code
void multiplyMatrices(int matrixA[5][5], int matrixB[5][5],int matrixC[5][5]){
the variables matrixA, matrixB and matrixC are pointers. In C++ it's impossible to have an array for a function parameter. It automatically gets converted to a pointer. It's also true that the syntax for accessing an array is identical to the syntax for accessing a pointer.
If you want to make it explicit that you are using pointers then rewrite your code like this
void multiplyMatrices(int (*matrixA)[5], int (*matrixB)[5],int (*matrixC)[5]){
Now you can see that matrixA, matrixB and matrixC pointers to arrays of 5 integers. You don't have to make any other changes. And in fact this change is exactly what the compiler does when you try to use an array as a function parameter.
Here's a good looking link that explains how pointers and arrays compare. The link talks about C, but the rules are the same in C++. Have a read it will probably help you understand better than I can.

Merge sort not working completely

The code that I have made for merge sort is given below. The thing is that on giving the input the output is 3 2 1 5 0. What is going wrong?
#include <iostream>
#include <cmath>
using namespace std;
int d[100];
void merge(int a[], int b[], int c[], int n)
{
int n2=floor(n/2);
int i=0, j=0, k=0;
while(i<n2 && j<(n-n2))
{
if(b[i]<c[j])
{
d[k++]=b[i++];
}
else if(b[i]>c[j])
{
d[k++]=c[j++];
}
}
if(i==n2)
{
if(j<(n-n2))
{
d[k++]=c[j++];
}
}
if(i<n2)
{
d[k++]=b[i++];
}
}
void mergesort(int a[], int n)
{
int n2=floor(n/2);
int b[50],c[50];
int i,j=0,k=0;
for(i=0;i<n2;i++)
{
b[i]=a[k++];
}
while(k<n)
{
c[j++]=a[k++];
}
merge(a,b,c,n);
}
int main()
{
int a[]={5,4,3,2,1};
int n=5;
mergesort(a,n);
for(int i=0;i<n;i++)
{
cout<<d[i]<<endl;
}
}
The main problem is that the arrays (b and c) passed to merge are not sorted.
Other problems are that the algorithm is not recursive and that merge
does not always put all numbers from b and c into a.
A version that seems to work with minimal changes to your code would be
void merge(int a[], int b[], int c[], int n)
{
int n2=floor(n/2);
int i=0, j=0, k=0;
while(k<n)
{
if((j == (n-n2) || b[i]<c[j]) && i < n2)
{
a[k++]=b[i++];
}
else
{
a[k++]=c[j++];
}
}
}
void mergesort(int a[], int n)
{
int n2=floor(n/2);
int b[50],c[50];
int i,j=0,k=0;
for(i=0;i<n2;i++)
{
b[i]=a[k++];
}
while(k<n)
{
c[j++]=a[k++];
}
if(n2 > 1) {
mergesort(b, n2);
}
if(n - n2 > 1) {
mergesort(c, n - n2);
}
merge(a,b,c,n);
}
int main()
{
int a[]={5,4,3,2,1};
int n=5;
mergesort(a,n);
for(int i=0;i<n;i++)
{
cout<<a[i]<<endl;
}
}
It is conventional to call merge_sort recursively in order to sort each subrange until the subrange is just one long then merge these together.
In your mergesort, b takes the first n/2 values of a, that is 5 and 4.
c takes the remaining values 3,2,1.
You then call merge (BTW Why do you pass a[] to this? It isn't used)
The first loop
while(i<n2 && j<(n-n2))
will have n2 = 2 and n-n2 = 5-2 = 3
This puts 3 at the start since b[0]>c[0]=3 and 2 next since b[1]>c[1]=2 and 1 at d[2] for similar reasons.
Since you don't recurse you won't sort these.
You then finish the while loop with i = 0 which is less than n2.
You just say
if(i<n2)
so you just copy the first thing from b which is 5.
All this gives 3, 2, 1, 5, and 0 because you made d global.
The input for merge need to be sorted arrays, as Philip mentioned before. Mergesort is recursive. For this you need to divide them till you reach a point where you only have one element in the array (so it is sorted) and merge all arrays to become the sorted result for the input. Wikipedia is your friend to understand the algorithm: Mergesort
Btw: You need to ensure that one of both cases in the comparison in the merge checks also on equality of the values.
Philip is right, there's no recursive in your code at all.
However, there are some more errors. I've marked it with annotations, just as a postscript of Philip's.
#include <iostream>
#include <cmath>
using namespace std;
int d[100];
void merge(int a[], int b[], int c[], int n)
{
int n2=floor(n/2);
int i=0, j=0, k=0;
while(i<n2 && j<(n-n2))
{
if(b[i]<c[j])
{
d[k++]=b[i++];
}
else if(b[i]>c[j])
{
d[k++]=c[j++];
}
/***************************************************/
/* What if b[i] == c[j] here? */
/* Your code will drop into an infinity loop. */
/***************************************************/
}
if(i==n2)
{
if(j<(n-n2))
/****************************************************/
/* Use **while** here? */
/* Because there may be more than one elements left */
/* in c[]. */
/****************************************************/
{
d[k++]=c[j++];
}
}
if(i<n2)
/***************************************************/
/* Use **while** here? - With the same reason */
/***************************************************/
{
d[k++]=b[i++];
}
}
void mergesort(int a[], int n)
{
int n2=floor(n/2);
int b[50],c[50];
int i,j=0,k=0;
for(i=0;i<n2;i++)
{
b[i]=a[k++];
}
while(k<n)
{
c[j++]=a[k++];
}
merge(a,b,c,n);
}
int main()
{
int a[]={5,4,3,2,1};
int n=5;
mergesort(a,n);
for(int i=0;i<n;i++)
{
cout<<d[i]<<endl;
}
}
template <typename T>
void merge(T arr[], int begin, int mid, int end)
{
int len = end - begin;
T *temp = new T[len];
int i = begin;
int j = mid + 1;
int k = 0;
while (i <= mid && j <= end)
{
if(arr[i] <= arr[j])
temp[k++] = arr[i++];
else
temp[k++] = arr[j++];
}
while (i <= mid)
temp[k++] = arr[i++];
while(j <= end)
temp[k++] = arr[j++];
memcpy(arr + begin, temp, len*sizeof(T));
delete []temp;
}
template <typename T>
void mergeSort(T arr[], int begin, int end)
{
if (begin >= end)
return;
int mid = (end + begin) / 2;
mergeSort(arr, begin, mid);
mergeSort(arr, mid + 1, end);
merge(arr, begin, mid, end);
}

Count the number of component wise comparisons in quicksort algorithm.

I'm trying to count the number of comparisons my quicksort algorithm makes for an array size of 500. I know that the best case for quicksort with partition is nlogn-n+1. So for an array size of 500, the best case number of component wise comparisons would be about 3983. However, when I run my code, I'm getting 2400 comparisons or so, depending on the array the random function generates. Am I counting the number of component wise comparisons wrong? Please help.
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
int count_500 = 0;
int partition(int *S,int l, int u);
void swap(int &val1, int &val2);
void Quicksort(int S[],int low, int hi);
void exchange(int list[], int p, int q);
int median_of_3(int list[], int p, int r);
void Quicksort_M3(int S[], int low, int hi);
int main()
{
int S1_500[500];
int S2_500[500];
int S3_500[500];
int S1_200[200];
int S2_200[200];
int S3_200[200];
int S1_8[8];
int S2_8[8];
int S3_8[8];
srand ( time(NULL) );
for(int i=0; i<500; i++)
{
S1_500[i] = rand()%1000;
S2_500[i] = rand()%1000;
S3_500[i] = rand()%1000;
}
for(int i=0; i<200; i++)
{
S1_200[i] = rand()%500;
S2_200[i] = rand()%500;
S3_200[i] = rand()%500;
}
for(int i=0; i<8; i++)
{
S1_8[i] = rand()%100;
S2_8[i] = rand()%100;
S3_8[i] = rand()%100;
}
Quicksort(S1_500,0,499);
for(int i=0; i<500; i++)
{
cout << S1_500[i] << endl;
}
cout << "Number of component wise comparisons is: " << count_500 << endl;
}
int partition(int *S,int l, int u)
{
int x = S[l];
int j = l;
for(int i=l+1; i<=u; i++)
{
if(S[i] < x)
{
count_500++; // Count the component wise comparison
j++;
swap(S[i],S[j]);
}
}
int p = j;
swap(S[l],S[p]);
return p;
}
void swap(int &val1, int &val2)
{
int temp = val1;
val1 = val2;
val2 = temp;
}
void Quicksort(int S[],int low, int hi)
{
if (low < hi)
{
int p = partition(S,low,hi);
Quicksort(S,low,p-1);
Quicksort(S,p+1,hi);
}
}
You want the count_500++; outside the if statement. You're only counting the comparisons, where the result is true.
Change
if(S[i] < x)
{
count_500++; // Count the component wise comparison
...
}
to
count_500++; // Count the component wise comparison
if(S[i] < x)
{
...
}