I have a modified version of quicksort in my program that is instructed to sort pairs of numbers by the sum of their squares ( for example: -4,1 > 2,2). My program works fine with positive integers, but when I use too many negative integers the program crashes (any more than one or two negative numbers will cause a crash). I think I'm trying to access or sort undefined parts of the array that is storing the integers. What is it about array storage that I am forgetting? Or is the problem elsewhere?
void swap(int *a,int *b);
int square(int num);
int abs_value(int num);
void quicksort(int arr[],int first,int last);
int main()
{
int num_of_pts;
int num1;
int num2;
printf("Enter number of points: ");//points are coordinates on the xy axis
scanf("%d", &num_of_pts); //that's why there is double
int unsorted_pts_arr[2*num_of_pts];//the amount of storage in the array
for(int i=0; i<num_of_pts; i++){
printf("Enter Point: ");
scanf(" %d",&num1);
scanf(" %d",&num2);
unsorted_pts_arr[2*i]=num1;
unsorted_pts_arr[2*i+1]=num2;
}
quicksort(unsorted_pts_arr,0,num_of_pts);
printf("Sorted Points:");
for(int j=0; j<num_of_pts; j++)
printf(" (%d,%d)",unsorted_pts_arr[2*j],unsorted_pts_arr[2*j+1]);
return 0;
}
void swap(int *a,int *b)
{
int temp;
temp = *b;
*b = *a;
*a = temp;
}
int square(int num)
{
num=abs_value(num);
num*=num;
return num;
}
int abs_value(int num)
{
if(num<0) return -num;
else return num;
}
void quicksort(int arr[],int first,int last)
{
int pivot,j,i;
if(first<last){
pivot=first;
i=first;
j=last;
while(i<j){
while((square(arr[2*i])+square(arr[2*i+1]))<=
(square(arr[pivot])+square(arr[pivot+1]))
&&i<last)
i++;
while((square(arr[2*j])+square(arr[2*j+1]))>
(square(arr[pivot])+square(arr[pivot+1])))
j--;
if(i<j){
swap(&arr[2*i],&arr[2*j]);
swap(&arr[2*i+1],&arr[2*j+1]);
}
}
swap(&arr[pivot],&arr[2*j]);
swap(&arr[pivot+1],&arr[2*j+1]);
quicksort(arr,first,2*j-1);
quicksort(arr,2*j+1,last);
}
}
Main problem
You are most likely accessing the array out of bounds by using 2*j-1 and 2*j+1 as the array indices in the recursive calls.
quicksort(arr,first,2*j-1);
quicksort(arr,2*j+1,last);
When you call quicksort from main, last is equal to num_of_pts. It makes sense that in the recursive calls, you should use j and j+1.
quicksort(arr,first,j);
quicksort(arr,j+1,last);
Suggestion for minor improvement
Implementation of square can be simpler.
int square(int num)
{
return num*num;
}
The last index is num_of_pts-1, so
quicksort(unsorted_pts_arr,0,num_of_pts);
must rather be
quicksort(unsorted_pts_arr, 0, num_of_pts-1);
pivot is used like i and j to index a pair of numbers in arr, so it must be doubled as well:
(square(arr[pivot])+square(arr[pivot+1]))
(both occurences) must be
square(arr[2*pivot])+square(arr[2*pivot+1])
quicksort is passed indexes to pairs of numbers (as in main), so the arguments of the recursive call also must not be doubled:
quicksort(arr,first,2*j-1);
quicksort(arr,2*j+1,last);
must be
quicksort(arr, first, j-1);
quicksort(arr, j+1, last);
Related
I was asked to write a recursive code to print an array. A friend showed me this code:
include <stdio.h>
int i=0;
void print(int A[], int n)
{
if(i<n)
{
printf("%d ", A[i]);
i++;
print(A, n);
}
}
int main()
{
int A[3]={3, 5, 2};
print(A, 3);
return 0;
}
Technically, it is recursive because the function calls itself, but I think trivially !! It does not break the problem into smaller problems or anything like that. So, it felt like cheating. Faking as if it is recursion.
Can the function in this code be consider recursive? Is this a fine way to use recursion?
What about in this form:
#include <stdio.h>
void print(int A[], int n, int i)
{
if(i<n)
{
printf("%d ", A[i]);
print(A, n, i+1);
}
}
int main()
{
int A[3]={3, 5, 2}, i=0;
print(A, 3, i);
return 0;
}
Can the function in this code be consider recursive?
Yes, recursion occurs when the function can call itself, either directly or indirectly.
Is this a fine way to use recursion?
No. Although some compilers may optimize the code, code risks incurring n levels of recursion and causing stack overflow
A better alternative is to halve the problem. This breaks the problem in 2 at each step.
void print(int A[], int n, int i) {
if (i<n) {
A += i; n -= i; // zero offset A and n
int mid = n/2;
print(A, mid, 0); // print left side of A
printf("%d ", A[mid]); // print middle of A
int right = n - mid - 1;
print(A + mid + 1, right, 0); // print right side of A
}
}
If n was 1000, the above could incur a recursion depth of log2(1000) or about 10 instead of 1000. An unbounded n is a reason recursion can be abused. Insure that the recursion depth is not excessive.
Notice that parameter i is not really needed.
void printA(int A[], size_t n) {
if (n > 0) {
size_t mid = n/2;
printA(A, mid); // print left side of A
printf("%d ", A[mid]); // print middle of A
size_t right = n - mid - 1;
printA(A + mid + 1, right); // print right side of A
}
}
Yes, this is a recursive function, since it calls itself.
Additionally, the function does break the problem to smaller problems - in this case, precisely one smaller problem: printing the array starting from index i+1 instead from index i. Since the bound is greater than i, the problem is smaller.
In other words, the recursion is well founded: the value of n-i is decreasing at each call, and the edge case of n-i==0 is handled trivially, not recursively.
Regardless of the number of lines in a function, it is recursive if it calls itself.
void print(int A[], int n) {
if(n == 0)
printf("%d", *A);
print(++A, --n);
}
Instead of using static variable you can pass the starting element address and last elements address of the array and do the same task.
void print(int *A_start, int *A_end) {
if(A_start < A_end) { /* call the function itself until A_start not reaches A_end */
printf("%d ", *A_start);
A_start++;
print(A_start,A_end);
}
}
int main() {
int A[3]={3, 5, 2};
int ele = sizeof(A)/sizeof(A[0]);
print(A,A+ele);
return 0;
}
I have 2 arrays. I read them trough a function. Then I sum them trough another function and print the sum array trough another function. I have to use pointers all the time. Problem is, it prints the sum of the last two elements of the array as the whole sum array. How can I fix this?
#include<stdio.h>
void read(int *pdato);
void print(int *pdato);
void sum(int *pdato1,int *pdato2, int *pdato);
int main(){
int A[5],B[5],C[5],i;
printf("Data for first array:\n");
read(A);
printf("Data for the second array\n");
read(B);
sum(A,B,C);
printf("Result:\n");
print(C);
return 0;
}
void read(int *pdato){
int i;
for(i=0;i<5;i++){
printf("[%d]:",i);
scanf("%d",pdato);
}
}
void sum(int *A,int *B, int *C){
int i;
for(i=0;i<5;i++){
*(C+i)=*(A+i)+*(B+i);
}
}
void print(int *pdato){
int i;
for(i=0;i<5;i++){
printf("[%d]:%d\n",i,*pdato);
}
}
Should be
printf("[%d]:%d\n",i,pdato[i]);
and
scanf("%d",&pdato[i]);
Building off of #Massey101, here is the answer without using array notation:
Should be
printf("[%d]:%d\n",i,*(pdato + i));
and
scanf("%d",pdato + i);
Another solution is below. Increment pointer after every data read to point to correct memory location to store inputs.
for(i=0;i<5;i++) {
scanf("%d",pdato);
pdato++;
}
Increment pointer while printing results, so that it will fetch results from correct memory location as show below
for(i=0;i<5;i++) {
printf("[%d]:%d\n",i,*pdato);
pdato++;
}
I am trying to implement the Heap sort algorithm provided in Cormen. My code is as follows :
#include<stdio.h>
#include<conio.h>
void max_heapify(int *,int);
void build_max_heap(int *,int);
void heapsort(int *,int);
void swap(int,int);
int heapsize;
int main()
{
int *arr,n,i;
printf("Enter no. of elements = ");
scanf("%d",&n);
arr=(int *)malloc(sizeof(int)*n);
for(i=0;i<n;i++)
{
printf("Enter array elements = ");
scanf("%d",&arr[i]);
}
//heapsize = n;
heapsort(arr,n);
printf("\nAfter heapsort \n");
for(i=0;i<n;i++)
{
printf("%d ",arr[i]);
}
return 0;
}
void heapsort(int *arr,int len)
{
int i;
build_max_heap(arr,len);
for(i= len-1;i>=1;i--)
{
swap(&arr[0],&arr[i]);
heapsize = heapsize -1;
max_heapify(arr,0);
}
}
void max_heapify(int *arr,int i)
{
int l=2*i,r=2*i+1,largest;
if(l<heapsize && arr[l]>arr[i])
largest = l;
else
largest = i;
if(r<heapsize && arr[r]>arr[largest])
largest = r;
if(largest != i)
{
swap(&arr[i],&arr[largest]);
max_heapify(arr,largest);
}
}
void build_max_heap(int *arr,int len)
{
heapsize = len;
int i;
for(i =len/2;i>=0;i--)
{
max_heapify(arr,i);
}
}
void swap(int *a ,int *b)
{
int temp = *a;
*a= *b;
*b= temp;
}
I cannot figure out what exactly is wrong in my code. The array is not getting sorted.In fact the original array is getting printed. Where am I going wrong?
Your swapfunction takes the arguments by value. So the original values are copied and the copies are swapped instead of the originals.
swap( int *a, int *b)
1) Fix swap, you're passing by value. Which means after swap is called nothing was changed!
2) The max_heapify function is wrong. Your left and right child calculation is off by 1. When you swap, you swap an index with an array value, yikes.
3) heapsort for-loop is wrong. You should put the first element (largest one in the heap) to the last index of the current heap, decrease the size of heap so the last element is part of the sorted list and not the heap. Then you perculate down from the root, not from the last element. Should be:
for(i= len-1;i>=1;i--)
{
swap(arr[0],arr[i]);
heapsize = heapsize -1;
max_heapify(arr,0);
}
You observe that your array is not getting sorted at all. Try working up to a complete heap sort in increments. So, as a debugging technique, create a copy of this code and replace the heapsort with a bubble sort. (bubble sorts are much easier to code). Get the bubble sort to work, this includes passing parameters and print the array before and after the sort.
Then do the heap sort.
The algorithm listed in Cormen seems to have a mistake.
Simply change the following line in your code:
max_heapify(arr,0); \In heapsort function
with
build_max_heap(arr,heapsize);
I've got a function thats able to produces 2 arrays, one when the index 'i' is even and one when the index 'i' is odd, so I end up with two arrays. The even 'i' array is called W_e and made of N elements, the odd 'i' array is called W_o and also made of N elements.
I now need to be merge these two arrays into another array Wn (which has 2*N elements) such that it looks like Wn=[W_e[0],W_o[0],W_e[1],W_o[1],...,W_e[N-1],W_o[N-1]] but I'm not sure how to do it. I tried to use nested loops but it didn't work. The arrays W_e and W_o are produced correctly according to my calculations, I'm just unable to combine the entries into one array.
This is what I have so far. I have not done anything in the main function except call the function which is giving me trouble "double *MakeWpowers(int N);". Please keep in mind this works for N>2, I have not yet dealt with N=1 or N=2.
Any help will be greatly appreciated. Thank you!!
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
#define pi 4*atan(1)
double *MakeWpowers(int N);
void print_vector(double *x,int N);
double *make_vector(double *x,int N);
int main(void)
{ int N;
double *Wn;
printf("\n Please enter the size of the NxN matrix:\n");
scanf("%d",&N);
Wn=MakeWpowers(N);
//print_vector(Wn,N);
free(Wn);
return(0);
}
double *MakeWpowers(int N)
{
double *Wn,*W_e,*W_o;
int i,j;
Wn=make_vector(Wn, 2*N);
W_e=make_vector(W_e, N);
W_o=make_vector(W_o, N);
for(i=0;i<=N-1;i++)
{
if(i%2==0)
{
W_e[i]=cos((2*i*pi)/N);
}
else
{
W_o[i]=sin((2*i*pi)/N);
}
}
printf("\nThis is the even vector W_e:\n");
print_vector(W_e, N);
printf("\nThis is the odd vector W_o:\n");
print_vector(W_o, N);
for(j=0;j<2*N;j++)
{
if(j%2==0)
{Wn[j]=W_e[i];}
//++i;}
else
{Wn[j]=W_o[i];}
//++i;}
printf("\nthis is Wn:\n\n");
print_vector(Wn, 2*N);
//Wn[j]=W_o[i];
//j++;
}
return(Wn);
}
void print_vector(double *x,int N)
{
int i;
for (i=0; i<N; i++)
{
printf ("%9.4f \n", x[i]);
}
printf("\n");
}
double *make_vector(double *x,int N)
{ int i;
double xi;
x=(double *)malloc((N)*sizeof(double));
for(i=0;i<N;i++)
{
x[i]=(double)xi;
}
return(x);
}
Here's the general logic to it:
LET a, b, merge BE ARRAYS
FOR k IN 0..length(a)
merge[2*k] = a[i]
merge[2*k+1] = b[i]
RETURN merge
a makes the even entries (2k), b the odd ones (2k+1).
This is probably wrong
double *make_vector(double *x,int N)
{ int i;
double xi;
You have to initialize variable xi same thing goes for *Wn,*W_e,*W_o
I am trying to create a program in C that removes duplicate values in an integer array. My strategy is to first sort the array via a selectionsort function, and then call a function removedup that removes any consecutive, duplicate values in the array.
My code:
#include <stdio.h>
#include "simpio.h"
#define n 10
void GetArray(int a[]);
void SelectionSort(int a[]);
int FindMax(int a[], int high);
void swap(int a[], int p1, int p2);
int removedup(int a[]);
void printArray(int a[]);
main()
{
int a[n];
GetArray(a);
SelectionSort(a);
printf("The original, sorted array is\n");
printArray(a);
printf("The array with removed duplicates \n");
printArray(removedup(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,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;
}
void swap(int a[], int p1, int p2)
{
int temp;
temp=a[p2];
a[p2]=a[p1];
a[p1]=temp;
}
int removedup(int a[])
{
int i, count, OutArray[count], j;
count=0;
for(i=0;i<n-1;i++)
{
if(a[i]==a[i+1])
{
a[i+1]=a[i+2];
count++;
}
}
count++;
for(j=0;j<count;j++)
{
OutArray[i]=a[i];
}
return OutArray;
}
I have two questions:
1) How do I fix the error the compiler in giving me in the main body when calling removedup inside the printarray function, saying "invalid conversion from int to int*"? (line 22)
2) How do I accurately define the size of OutArray[] in the removedup function? Currently I have it defined as the size variable, but the value of this variable isn't accurately defined until after the declaration of OutArray.
Notice your prototypes ...
int removedup(int a[]);
void printArray(int a[]);
And also notice you're calling printArray() with the result of removedup().
printArray(removedup(a));
The result of removedup() is an int; printarray() requires a int[].
int and int[] are not compatible.
I suggest you remove duplicates and print array in two distinct statements.
You should be able to fix the compiling problems after reading comp.lang-c FAQ on arrays and pointers.
After you get your array sorted, you can use the following function to remove the duplicates:
int dedup(int arr[], int size) {
int curr = 0, next = 0;
while (next < size) {
while (next < size && arr[next] == arr[curr])
next++;
if (next < size)
arr[++curr] = arr[next++];
}
return size ? curr+1 : 0;
}
It takes two arguments, the array and its size. The duplicates are removed in-place, which means that the array is modified, without allocating a new array to store the unique elements.
Remember that the dedup function expects the elements to be sorted! I've noticed you are using your own implementation of selection sort, which makes me think this is homework. In that case, I feel a little reluctant on giving you a complete solution, although understanding it should be a good exercise anyway.
EDIT: I should've explained the last line of code.
return size ? curr+1 : 0; is equivalent to:
if (size)
return curr+1;
else
return 0;
Just a shorter way of saying the same thing.