C sorting explanation and trouble - c

I'm having trouble solving this problem. I'm supposed to sort then search an array (through binary search) but I'm having trouble in how to get the size of an array I think.
int binarySearch( int Arr[], int value)
{
int low = 0;
int high =sizeof(Arr)/sizeof(int);
int mid = (low+high)/2;
printf("%d\n",high);
while (low <= high && Arr[mid] != value)
{
if( Arr[mid] < value)
{
low = mid+1;
}
else
{
high = mid-1;
}
mid = (low+high)/2;
}
if (low > high)
{
mid= -1;
}
return mid;
}
int main()
{
BubbleSort( Array, 10);
int pos = binarySearch(Array, 3);
printf("The sorted array is: ");
PrintArray( Array, 10);
printf("\n");
printf("Now lets look for number 3\n");
printf("The number was located in space %d\n", pos);
PrintArray( Array, 10);
}
But all I keep getting is:
./search
2 \\This is where I wanted to see what I was getting as the size of my array, 2???
The sorted array is: 0 1 2 3 4 5 6 7 8 9
Now lets look for number 3
The number was located in space -1
0 1 2 3 4 5 6 7 8 9

Using sizeof on an array which is a parameter to a function won't work as you expect.
When an array is passed to a function, it decays to a pointer to the first element of the array.
So this:
int binarySearch( int Arr[], int value)
Is the same as this:
int binarySearch( int *Arr, int value)
And sizeof(Arr) is the same as calling sizeof(int *).
You need to pass the size of the array as a separate parameter to your function.

What others have said about sizeof is correct... but there's even more information binarySearch needs to do its job:
int binarySearch( int Arr[], int low, int high, int value)
{
int mid = (low+high)/2;
...
initially called as
binarySearch (Array, 0, 9, 3);
or better yet
binarySearch (Array, 0, SIZE-1, 3);
This is because binary search doesn't always start at 0 and doesn't always end at the end of the array.
Also note that last, the location of the last item, isn't the size of the array, but one less, because of C++'s 0-based counting.
For another look at how to do this, see this page, scroll down to the C++ section (which in this case has code that compiles fine as C): http://www.algolist.net/Algorithms/Binary_search

Related

Binary search array showing -1 as result

#include<stdio.h>
int binary_search(int arr[], int size ,int element){
int low, mid, high;
low=0;
high=size-1;
//start of search
while(low<=high)
{
mid = (low + high)/2;
if(arr[mid] == element){
return mid;
}
if(arr[mid]<element){
low= mid+1;
}
else{
high = mid-1;
}
}
//end of search
return -1;
}
int main(){
int arr[20]={1,20,31,44,54,68,70,85};
int size= sizeof(arr)/sizeof(int);
int element=44;
int Si= binary_search(arr,size,element);
printf("Element was found at index: %d \n",Si);
return 0;
}
why does my code returns -1 everytime .
I tried changing arr[20] to arr[] in main function and it started working fine.
Can someone explain me the reason behind this?
This line of code creates an integer array of length 20, with all the elements after 85 being initialized to zeros.
int arr[20]={1,20,31,44,54,68,70,85};
The sizeof operator gives the size, in bytes, of the integer array arr of length 20, which causes the value of size to be 20. This causes the binary search algorithm to fail, as it does not deal with arrays that are not sorted.

C recursive program to find the maximum element from array

So I have a task in my training that sounds like this:
Write a subprogram that will recursively find the maximum element from an array and also write the main function to call it.
What I failed to fully understand is what recursion is. I wanted to ask you guys if my code is recursive or not. And if not what changes should I make/ what recursion really means?
#include <stdio.h>
int find_maximum(int[], int);
int main() {
int c, array[100], size, location, maximum;
printf("Input number of elements in array\n");
scanf("%d", &size);
printf("Enter %d integers\n", size);
for (c = 0; c < size; c++)
scanf("%d", &array[c]);
location = find_maximum(array, size);
maximum = array[location];
printf("Maximum element location = %d and value = %d.\n", location + 1, maximum);
return 0;
}
int find_maximum(int a[], int n) {
int c, max, index;
max = a[0];
index = 0;
for (c = 1; c < n; c++) {
if (a[c] > max) {
index = c;
max = a[c];
}
}
return index;
}
Thank you all for your time!
Problems that are well-suited to recursion can be broken down into smaller, simpler subproblems. This is one of the things that gives recursion its power. When trying to use recursion to solve a problem, it usually seems best to try to break the problem down into simpler subproblems in finding your way to a solution.
You might notice that in finding the maximum value stored in an array, it is either the value of the first element, or the maximum value of the remaining elements. This breaks the problem into two parts: if the first element is larger than any remaining elements, you are done; otherwise, you must continue and see if the next element is larger than the remaining elements. In code, this might look like:
int max_in(size_t rest_sz, int *rest)
{
int curr_val = rest[0];
if (rest_sz == 1) {
return curr_val;
}
int max_in_rest = max_in(rest_sz-1, rest+1);
return curr_val > max_in_rest ? curr_val : max_in_rest;
}
Here, there is a base case: if rest_sz is 1, there is no need to look further; the value of first element (curr_val = rest[0]) is the maximum, and that value is returned. If the base case is not satisfied, execution of the function continues. max_in_rest is the result from the recursive function call max_in(rest_sz-1, rest+1). Here rest_sz-1 indicates the number of elements remaining in the portion of the array indicated by rest+1. In the new function call, the base case is met again, and eventually this case will be true since rest_sz is decremented with each recursive call. When that happens, the value of curr_val in the current stack frame will be returned; note that this value is the value of the last element in the array. Then, when the function returns to its caller, max_in_rest in that frame will get the returned value, after which the larger of curr_val or max_in_rest is returned to the previous caller, and so on, until finally control is returned to main().
Using pencil and paper to diagram each function call, the values of its variables, and what is returned would help to understand exactly how this recursion works.
You can apply the same method to solving the problem of finding the index of the maximum value of an array. In this case, if the value of the first element is greater than the value of any remaining elements, then the index of the maximum element is the index of the first element; otherwise the index of the maximum element is the index of the maximum value of the remaining elements. In code, this might look like:
size_t find_max_r(int arr[], int *rest, size_t rest_sz, size_t curr_ndx)
{
if (rest_sz == 1) {
return curr_ndx;
}
int curr_val = arr[curr_ndx];
size_t max_in_rest_ndx = find_max_r(arr, rest+1, rest_sz-1, curr_ndx+1);
int max_in_rest = arr[max_in_rest_ndx];
return curr_val >= max_in_rest ? curr_ndx : max_in_rest_ndx;
}
There is just a little more information to keep track of this time. Here, if the base case is satisfied, and rest_sz is 1, then there is no reason to look further, the current index curr_ndx is the index of the maximum value. Otherwise, find_max_r() is recursively called, with rest incremented to point to the remaining elements of the array, and rest_sz suitably decremented. This time, curr_ndx is keeping track of the current index with respect to the original array, and this value is passed into each function call; also, a pointer to the first element of the original array, arr, is passed into each function call so the index value curr_ndx can access the values from the original array.
Again, when the base case is reached, the current position in the array will be the end of the array, so the first elements to be compared in the return statement will be towards the end of the array, moving towards the front of the array. Note that >= is used here, instead of > so that the index of the first maximum value is returned; if you instead want the index of the last maximum value, simply change this to >.
Here is a complete program. Note the use of the helper function find_max() to call the recursive function find_max_r(), which allows the caller to use a function with the same signature that the posted code uses (except for the use of size_t types, which is really the correct type for array indices):
#include <stdio.h>
int max_in(size_t sz, int *rest);
size_t find_max(size_t sz, int arr[]);
size_t find_max_r(int arr[], int *rest, size_t rest_sz, size_t curr_ndx);
int main(void)
{
int array[] = { 2, 7, 1, 8, 2, 5, 1, 8 };
size_t array_sz = sizeof array / sizeof array[0];
int max_val = max_in(array_sz, array);
printf("Maximum value is: %d\n", max_val);
size_t max_ndx = find_max(array_sz, array);
printf("Maximum value index: %zu\n", max_ndx);
return 0;
}
int max_in(size_t rest_sz, int *rest)
{
int curr_val = rest[0];
if (rest_sz == 1) {
return curr_val;
}
int max_in_rest = max_in(rest_sz-1, rest+1);
return curr_val > max_in_rest ? curr_val : max_in_rest;
}
size_t find_max(size_t sz, int arr[])
{
int *rest = arr;
return find_max_r(arr, rest, sz, 0);
}
size_t find_max_r(int arr[], int *rest, size_t rest_sz, size_t curr_ndx)
{
if (rest_sz == 1) {
return curr_ndx;
}
int curr_val = arr[curr_ndx];
size_t max_in_rest_ndx = find_max_r(arr, rest+1, rest_sz-1, curr_ndx+1);
int max_in_rest = arr[max_in_rest_ndx];
return curr_val >= max_in_rest ? curr_ndx : max_in_rest_ndx;
}
Program output:
Maximum value is: 8
Maximum value index: 3
Think of calculating the maximum number in an array as the number which will be maximum of the first element and the maximum of the remaining elements of the array. Something like: max(first_elem, max(remaining_elems)).
The actual recursive function: find_max quite simple, if there is just a single element in the array, that element is returned. Otherwise, we get the maximum of the first element and the remaining elements of the array.
#include <stdio.h>
// function to find the max of 2 numbers
int max(int x, int y)
{
return (x > y) ? x : y;
}
// the recursive function
int find_max(int *p, int n)
{
if (n == 1) return *p;
return max(*p, find_max(p + 1, n - 1));
}
int main(void)
{
int arr[] = {23, 3, 11, -98, 99, 45};
printf("max: %d\n", find_max(arr, sizeof arr / sizeof arr[0]));
}
No, your code does not use recursion. Recursion is when a function calls itself, or calls another function which leads to a call to itself again.
You can change your code like this to have a recursive, stateless function that can determine the maximum value of the array.
int find_maximum(int a[], int n) {
return find_maximum_r(a, 0, n);
}
int find_maximum_r(int a[], int index, int n) {
if (index + 1 == n) {
return a[index];
}
int maxRight = find_maximum_r(a, index + 1, n);
return a[index] > maxRight ? a[index] : maxRight;
}
No, your code is recursive only if you call the function find_maximum from itself directly or indirectly.
As your function is trying to get not only the maximum value, but also the position in the array, I have modified slightly the interface to return the reference (that is, a pointer to the value) so we can infer the position of the array element directly from the subtraction of element pointers. This way, I can pass to the function the array pointer directly and the array size, and then divide the array in two halves, and applying the same function to the two halves (it can be demonstrated that if some element is the maximum value of the array, it has to be greater than or equal to each half's maximum) For the same reason, I have modified some of the variables defined in your main() function, to allow for references to be used:
max.c
#include <stdio.h>
#include <assert.h>
int *find_maximum(int a[], int n); /* return a reference pointer to the maximum value */
int main() {
int c, array[100], size, *location, /* location must be a pointer */
maximum;
printf("Input number of elements in array\n");
scanf("%d", &size);
assert(size >= 1);
printf("Enter %d integers\n", size);
for (c = 0; c < size; c++)
scanf("%d", &array[c]);
location = find_maximum(array, size);
maximum = *location; /* access to the value is granted by pointer dereference */
printf("Maximum element location = %td and value = %d.\n",
location - array, /* pointer difference gives the array position */
maximum);
return 0;
} /* main */
/* somewhat efficient recursive way of a divide and conquer method
* to get the maximum element reference. */
int *find_maximum(int a[], int n)
{
if (n == 1) return a; /* array of 1 element */
int *left = find_maximum(a, n/2), /* left half begins at a
* and has n/2 elements */
*right = find_maximum(a + n/2, (n+1)/2); /* right half begins
* at a + n/2, and
* has (n+1)/2
* elements */
return *left > *right
? left
: right;
} /* find_maximum */
As you see, I have to divide by two, but as I have arrays of any length, I have to be careful not to leave out any element in the next step. This is the reason for using an array of (n+1)/2 elements in the right half of the recursive call to the function. I include n/2 elements in the first half (rounding down), I have to include (n+1)/2 elements (rounding up) in the right half, to be sure that I include all the array elements in the two halves.
First of all, recursion means - function calling itself.
And what you've written is not recursive function. I'll post the most simple way to find biggest or largest element in an array, using recursion.
#include<stdio.h>
#define N 5
int biggest(int num[], int n, int big)
{
if(n < 0)
return big;
else
{
if(big < num[n])
big = num[n];
return biggest(num, --n, big);
}
}
int main()
{
int a[N], i;
printf("Enter %d integer number\n", N);
for(i = 0; i < N; i++)
scanf("%d", &a[i]);
printf("Biggest Element in the array: %d\n", biggest(a, N - 1, a[0]));
return 0;
}
Source: C Program To Find Biggest Element of An Array using Recursion
NO it is not recursive function
to know about recursion this link is very useful https://www.khanacademy.org/computing/computer-science/algorithms/recursive-algorithms/a/recursion/
to make a recursion function to solve your problem try this
you can try this pseudo code declare your array global and a max=0 global and size global
int find_maximum(int i)
{
if (i == size )
return max;
else if ( max < array[i])
max =array [i];
return find_maximum(i+1);
}
where i is the array index
No, your program is certainly not recursive. As the definition, recursive function must call itself with a terminating condition.
Please read TutorialsPoint about recursion in C.
Update on #JonathanLeffler's comment:
Please note that the output in the reference will overflow.

Print the values of knapsack solution

I have the following solution for the knapsack problem:(wt[] is the weights array, val[] is the values array, n is the arrays size, index is the current item that we are trying (for the recursion) and arr is an array that represents weather or not item i was included in the solution.
int knapSack(int W, int wt[], int val[], int n, int index, int arr[])
{
if (n == index || W == 0)
return 0;
if (wt[index] > W)
return knapSack(W, wt, val, n, index+1 );
int with=val[index]+knapSack(W-wt[index], wt, val, n, index+1);
int without=knapSack(W, wt, val, n, index+1);
if(with>without){
arr[index]=1;
return with;
}
else{
arr[index]=0;
return without;
}
}
I am trying to print, in this recursive solution the items that are chosen, by setting the indexes of the taken ones in an array (res) to 1.
As I understand, if with>without, it means that I am choosing the current item, or item #index. So why is this not returning a right value?
I am using the recursive algorithm for a reason, I know using the memoization version can be easier here.
Example:
Weights: 5 6 7 10 11
Values: 2 4 5 6 9
W=25
Will return 5 ones in array res. When solution is 18 with items 2,3,5 (starting from index 1).
Premise 1: in your code, the recursion calls to knapSack are not passing arr, which should cause a compilation error, I assume it's just a copy/paste error.
Premise 2: with the data you proposed, the resulting arr value is not all 1 as you indicated, but 01011, which is still incorrect.
Consider the hypothetical situation in which, during the execution of your function, with is greater than without: during the with calculation arr is filled with the correct values; but then start the without calculation which is going to overwrite the arr values.
Since with is greater than without, the returned arr will be the wrong one, and this is the cause of the problem.
A simple fix would be to make a copy of the arr returned by the with calculation so it is not going to be overwritten by the without calculation, for example:
int with=val[index]+knapSack(W-wt[index], wt, val, n, index+1, arr);
// copy the "with" arr
int arrWith[n];
copyArr(arr, arrWith, n);
int without=knapSack(W, wt, val, n, index+1, arr);
if(with>without){
// restore the "with" arr
copyArr(arrWith, arr, n);
arr[index]=1;
return with;
}
else{
arr[index]=0;
return without;
}
copyArr is simply:
void copyArr(int arr[], int arrDest[], int n) {
int i;
for(i = 0; i < n; i++) {
arrDest[i] = arr[i];
}
}
With this fix the resulting value of arr is correctly 01101.

C: Recursive function - Binary search

I'm trying to build a recursive function which returns the address within a sorted array by comparing to the middle value and proceeding based on relative size. Should the value not be in the array, it is supposed to simply print NULL. Now the first part of the function works, however whenever a null is supposed to happen I get a segmentation fault. The code looks as follows:
#include <stdio.h>
int *BinSearchRec(int arr[], int size, int n){
if(n==arr[size/2]){
return &arr[size/2];
}
else if(n>arr[size/2]) {
return(BinSearchRec(arr, size+size/2, n));
}
else if(n<arr[size/2]) {
return(BinSearchRec(arr, size-size/2, n));
}
else{
return NULL;
}
}
main(){
int numb[]={2,7,8,9};
if((int)(BinSearchRec(numb, 4, 22)-numb)>=0) {
printf("Position: %d \n", (int)(BinSearchRec(numb, 4, 22)-numb)+1);
}
else{
printf("NULL \n");
}
}
Your recursive calls are wrong. In the first case you claim that the size of the array is 50% larger than originally, and you're passing the pointer wrong (you should pass the second "half" of the array).
In both cases, the size of the "array" is always half of what the function received. And in the second case, you need to pass a pointer to the second half of the array.
Something like
else if(n>arr[size/2]) {
return(BinSearchRec(arr + sizeof/2, size/2, n));
}
else if(n<arr[size/2]) {
return(BinSearchRec(arr, size/2, n));
}
You're also treating the returned value from the function wrong. It's not a value, it's a pointer to the value, you need to treat it as such. And it's okay to subtract one pointer from another (related) pointer, it's called pointer arithmetics.
In addition to what others have said about not dividing the array properly and not using the return value correctly, your function is missing a termination condition.
In your code, the las else will never be reached, because the three preceding conditions cover all possibilities: n is either smaller than, equal to or greater than arr[size/2].
You should test whether your subarray actually has elements before you access and compare them. Here's a revision of your code:
int *BinSearchRec(int arr[], int size, int n)
{
int m = size/2;
if (size == 0) return NULL;
if (n > arr[m]) return BinSearchRec(arr + m + 1, size - m - 1, n);
if (n < arr[m]) return BinSearchRec(arr, m, n);
return &arr[m];
}
And here's an example main that shows how you make use of the pointer that was returned. If the pointer is NULL, the number is not in the array and you cannot dereference the pointer.
int main()
{
int numb[] = {2, 7, 8, 9};
int n;
for (n = 0; n < 15; n++) {
int *p = BinSearchRec(numb, 4, n);
if (p) {
printf("%d: #%d\n", n, (int) (p - numb));
} else {
printf("%d: NULL\n", n);
}
}
return 0;
}
Instead of using a single size, it is easier to reason with 2 indexes (left and right) delimiting the sub-array you are exploring.
Modifying your code according to this approach gives:
#include <stdio.h>
#include <stdlib.h>
int *BinSearchRec(int arr[], int left, int right, int n){
if (left > right)
return NULL;
int mid = (left + right) / 2;
if(n == arr[mid])
return &arr[mid];
if(n > arr[mid])
return BinSearchRec(arr, mid + 1, right, n);
else
return BinSearchRec(arr, left, mid - 1, n);
}
int main(int argc, char *argv[]){
int numb[] = {2,7,8,9};
int *p = BinSearchRec(numb, 0, 3, 22);
if (p) {
printf("Position: %d \n", (int) (p - numb + 1));
} else {
printf("NULL \n");
}
return 0;
}

Why does this Quicksort work?

I find this Quicksort partitioning approach confusing and wrong, yet it seems to work. I am referring to this pseudocode. Note: they also have a C implementation at the end of the article, but it's very different from their pseudocode, so I don't care about that.
I have also written it in C like this, trying to stay true to the pseudocode as much as possible, even if that means doing some weird C stuff:
#include <stdio.h>
int partition(int a[], int p, int r)
{
int x = a[p];
int i = p - 1;
int j = r + 1;
while (1)
{
do
j = j - 1;
while (!(a[j] <= x));
do
i = i + 1;
while (!(a[i] >= x));
if (i < j)
{
int t = a[i];
a[i] = a[j];
a[j] = t;
}
else
{
for (i = 1; i <= a[0]; ++i)
printf("%d ", a[i]);
printf("- %d\n", j);
return j;
}
}
}
int main()
{
int a[100] = //{8, 6,10,13,15,8,3,2,12};
{7, 7, 6, 2, 3, 8, 4, 1};
partition(a, 1, a[0]);
return 0;
}
If you run this, you'll get the following output:
1 6 2 3 4 8 7 - 5
However, this is wrong, isn't it? Clearly a[5] does not have all the values before it lower than it, since a[2] = 6 > a[5] = 4. Not to mention that 7 is supposed to be the pivot (the initial a[p]) and yet its position is both incorrect and lost.
The following partition algorithm is taken from wikipedia:
int partition2(int a[], int p, int r)
{
int x = a[r];
int store = p;
for (int i = p; i < r; ++i)
{
if (a[i] <= x)
{
int t = a[i];
a[i] = a[store];
a[store] = t;
++store;
}
}
int t = a[r];
a[r] = a[store];
a[store] = t;
for (int i = 1; i <= a[0]; ++i)
printf("%d ", a[i]);
printf("- %d\n", store);
return store;
}
And produces this output:
1 6 2 3 8 4 7 - 1
Which is a correct result in my opinion: the pivot (a[r] = a[7]) has reached its final position.
However, if I use the initial partitioning function in the following algorithm:
void Quicksort(int a[], int p, int r)
{
if (p < r)
{
int q = partition(a, p, r); // initial partitioning function
Quicksort(a, p, q);
Quicksort(a, q + 1, r); // I'm pretty sure q + r was a typo, it doesn't work with q + r.
}
}
... it seems to be a correct sorting algorithm. I tested it out on a lot of random inputs, including all 0-1 arrays of length 20.
I have also tried using this partition function for a selection algorithm, in which it failed to produce correct results. It seems to work and it's even very fast as part of the quicksort algorithm however.
So my questions are:
Can anyone post an example on which the algorithm DOESN'T work?
If not, why does it work, since the partitioning part seems to be wrong? Is this another partitioning approach that I don't know about?
I think the partitioning is correct. 7 is the pivot. The original array is partitioned into a sub array of length 5 containing elements less than or equal to 7 and a sub array of length 2, containing elements greater or equal to 7.
Extending on from above here is what it should look like
void swap(int *a, int *b)
{
int x;
x = *a;
*a = *b;
*b = x;
}
int partition(int s[], int l, int h)
{
int i;
int p;/* pivot element index */
int firsthigh;/* divider position for pivot element */
p = h;
firsthigh = l;
for (i = l; i < h; i++)
if(s[i] < s[p]) {
swap(&s[i], &s[firsthigh]);
firsthigh++;
}
swap(&s[p], &s[firsthigh]);
return(firsthigh);
}
void quicksort(int s[], int l, int h)
{
int p;/* index of partition */
if ((h - l) > 0) {
p = partition(s, l, h);
quicksort(s, l, p - 1);
quicksort(s, p + 1, h);
}
}
int main()
{
int a[100] = //{8, 6,10,13,15,8,3,2,12};
{7, 7, 6, 2, 3, 8, 4, 1};
quicksort(a, 0, 7);
return 0;
}
From Wikipedia (I've emphasized the part that I think addresses your question directly):
This is the in-place partition
algorithm. It partitions the portion
of the array between indexes left and
right, inclusively, by moving all
elements less than or equal to
array[pivotIndex] to the beginning of
the subarray, leaving all the greater
elements following them. In the
process it also finds the final
position for the pivot element, which
it returns. It temporarily moves the
pivot element to the end of the
subarray, so that it doesn't get in
the way. Because it only uses
exchanges, the final list has the same
elements as the original list. Notice
that an element may be exchanged
multiple times before reaching its
final place. It should also be noted
that in case of pivot duplicates in
the input array, they can be spread
across left subarray, possibly in
random order. This doesn't represent a
partitioning failure, as further
sorting will reposition and finally
"glue" them together.
Could that be what you were missing?
You are getting confused between the index of the item and the iten value
Look at your header
int partition(int a[], int p, int r) ;
Now if we changed the data type on the array a to some weird data type you will see the problem
int partition( Otherdatatype a[], int p, int r) ;
You call the function from within your main with
partition(a, 1, a[0]);
See the problem a[0] is the value of the entry in a[0] not an index value.
Imagine a[0] had the value 200 in your code simply change the first item value to 200 and you will get a runtime error "attempt to access memory out of range" because if you follow
thru a[0] = 200 that is passed into partition as value r then follow what happens inside partition.
The thing to remember is this is a sort routine in your partition header the list in array a may not be of the same type as the indexes .. p and r of your header are clearly indexes referring to an index position and a is the list to be sorted.
Thus your main start to a sort is
partition(a, 0, items_in_array-1);
Do you see why? Array a runs from a[0] ... a[items_in_array-1]
So in your sample above you have preloaded 8 values into your array so your partition call from main should be
partition(a, 0, 7);

Resources