Binary search array showing -1 as result - arrays

#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.

Related

Methods of tracking pointer objects through functions in C

I'm stuck trying to implement pseudocode from an algorithm book. My code compiles and prints out the correct answer, except some of the information I want to print out is not displaying correctly. Here's what the console output looks like:
Correct Solution Tested:
max_left= 7
max_right= 10
sum= 43
Failing Outputs:
curr_cross_low = 17; curr_cross_high = -1; curr_cross_sum = 38
curr_cross_low = -1; curr_cross_high = -1; curr_cross_sum = 18
curr_cross_low = 32766; curr_cross_high = -272632720; curr_cross_sum = 43
max_left_full= 32766
max_right_full= -272632512
sum_full= 43
Program ended with exit code: 0
The first three values printed are the correct results arrived by brute implementation of one part of the algorithm. In the code, this is the function "findMaxCrossingSubarray" all by itself. The second part printed out is when I execute the full algorithm "findMaximumSubarray". I believe it should be printing out results that show approaching the solution. The final answer given by the variable "sum_full" appears to be correct since it matches the brute force solution which the book says is the correct answer.
I've been trying to find how I can print the correct max_left_full and max_right_full values and not what I believe is the memory address. I'm at a point where if I change a pointer in one place it makes the solution incorrect or print out a memory address as well.
Is there a simple way to find where I may be dropping the ball?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//returns a pointer to a value equal to the set of changes
int * returnPriceChanges(int sz, int A[]){
int MAX_SIZE = 256;
static int* C;
C = malloc(MAX_SIZE *sizeof(int));
int i;
for(i=0;i<sz-1;i++){
C[i]=A[i+1]-A[i];
}
return C;
}
int findMaxCrossingSubarray(int A[], int low, int mid, int high, int* max_left, int* max_right){
double left_sum = -INFINITY;
int sum = 0;
for(int i=mid;i>=low;i--){
sum=sum+A[i];
if(sum > left_sum){
left_sum = sum;
*max_left = i;
}
}
double right_sum = -INFINITY;
sum = 0;
for(int j=mid+1; j<=high;j++){
sum=sum+A[j];
if(sum > right_sum){
right_sum = sum;
*max_right = j;
}
}
return (*max_left, *max_right, left_sum+right_sum);
}
int findMaximumSubarray(int A[], int low, int high){
int curr_left_low, curr_left_high, curr_left_sum;
int curr_right_low, curr_right_high, curr_right_sum;
int curr_cross_low, curr_cross_high, curr_cross_sum;
int mid = 0;
int* temp_max_left, temp_max_right;
if(high==low){
return(low, high, A[low]);
}
else{
mid =floor((high+low)/2);
curr_left_low, curr_left_high, curr_left_sum = findMaximumSubarray(A, low, mid);
curr_right_low, curr_right_high, curr_right_sum = findMaximumSubarray(A, mid+1,high);
curr_cross_low, curr_cross_high, curr_cross_sum = findMaxCrossingSubarray(A, low, mid, high, &temp_max_left, &temp_max_right);
if(curr_left_sum>=curr_right_sum && curr_left_sum>=curr_cross_sum){
return (curr_left_low, curr_left_high, curr_left_sum);
}
else if(curr_right_sum>= curr_left_sum && curr_right_sum>=curr_cross_sum){
return (curr_right_low, curr_right_high, curr_right_sum);
}
else{
printf("curr_cross_low = %d; curr_cross_high = %d; curr_cross_sum = %d\n", curr_cross_low, curr_cross_high, curr_cross_sum);
return (curr_cross_low, curr_cross_high, curr_cross_sum);
}
}
}
int main(){
int prices[] = {100,113,110,85,105,102,86,63,81,101,94,106,101,79,94,90,97};
int szPrices = sizeof(prices)/sizeof(prices[0]);
int changes[szPrices-1];
int *P;
P = returnPriceChanges(szPrices,prices);
//set C = to list of changes
for(int i=0; i<szPrices-1; i++){
changes[i]=*(P+i);
}
int max_left, max_right, sum;
max_left, &max_right, sum = findMaxCrossingSubarray(changes, 0, 8, 16, &max_left, &max_right);
printf("\nCorrect Solution Tested: \nmax_left= %d \nmax_right= %d \nsum= %d\n\n", max_left, max_right, sum);
printf("\nFailing Outputs:\n");
int max_left_full, max_right_full, sum_full;
max_left_full, &max_right_full, sum_full = findMaximumSubarray(changes, 0, 16);
printf("\nmax_left_full= %d \nmax_right_full= %d\nsum_full= %d\n\n", max_left_full, max_right_full, sum_full);
return 0;
}
You cannot return tuples from functions in C. When you separate values using a comma in C, the whole expression simply evaluates to the last member.
So when you write:
a, b, c = some_function();
It really means:
/* do nothing */, /* do nothing */, c = some_function();
If you want to return a composite data structure, use a struct, i.e.
struct subarray
{
int low;
int high;
int sum;
};
void findMaximumSubarray(int A[], int low, int high, struct subarray * result);
If the struct is small and you are using a modern compiler, and not running on an embedded system, then you can also return the struct by value:
struct subarray findMaximumSubarray(int A[], int low, int high);
The latter syntax simplifies usage, but it can become an issue if you start returning huge structs this way.

C sorting explanation and trouble

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

Recursive way to find duplicate entries in array in C

I'm trying to write a recursive function to find duplicates in an array of integers. For example if the array is: {4, 1, 4, 3, 2, 3} it should returns 2.
I tried a mergesort-like approach but without success. Someone can help?
My try (works only with ordered arrays):
int count(int arr[], int bot, int top){
if(bot==top) return 0;
else{
int med = (bot+top)/2;
int n = count(arr, bot, med) + count(arr, med+1, top);
if(arr[med]==arr[med+1]) n++;
return n;
}
}
You are just checking if arr[med]==arr[med+1] which will have a problem when you have a case like 111 then the count will become two but the count should actually be one. So add an extra flag to check if the same element is repeated or not.
Sort the array. May be you can use merge sort or something to do that and then something like this should work!
#include <stdio.h>
int main(void) {
// your code goes here
int a[16] = {1,1,1,1,1,1,1,1,1,1,1,2,2,3,3,5};
int out = count(a,0,15);
printf("%d\n",out);
return 0;
}
int count(int arr[], int bot, int top){
int flag = 0;
if(bot==top) return 0;
else{
int med = (bot+top)/2;
int n = count(arr, bot, med) + count(arr, med+1, top);
if(arr[med]==arr[med+1])
{
flag = arr[med-1];
if(flag != arr[med])
n++;
}
return n;
}
}

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

Merge Sort in C compiles, but doesn't sort

I made this program to sort an array. It works fine, but it won't sort! Please help me find the error in my logic. Thanks
[UPDATE] It was able to work! I just brought down the i, j, and k as suggested below.Also, from i
#include <stdio.h>
#include <stdlib.h>
void mergesort(int[], int, int);
void merge(int [], int low, int mid, int hi); //function prototype
int main()
{
int arr[]={1,4,78,92,9};
mergesort(arr,0,5);
//after mergesort
for(int i=0; i<5; i++)
{
printf("%d, ", arr[i]);
}
system("pause");
return 0;
}
void mergesort(int aptr[], int low, int hi)
{
int mid =0;
int rightmax=0;
int leftmax=0;
if(low==hi)
{
return;
}
mid=(low+hi)/2;
mergesort(aptr, low, mid);
mergesort(aptr, mid+1, hi);
merge(aptr, low, mid, hi);
}
void merge(int aptr[], int low, int mid, int hi)
{
int j, i, k;
//copy contents of aptr to auxiliary b
for(i=low; i<=hi; i++)
{
bptr[i]=aptr[i];
}
// iterate through b as if they were still two arrays, lower and higher
//copy smaller elements first
i=low;
j=mid+1;
k=low;
while(i<= mid && j<=hi)
{
if(bptr[i]<=bptr[j])//<--put smaller element first
{
aptr[k++]=bptr[i++];
}
else
{
aptr[k++]=bptr[j++];
}
}
// copy back first half just in case
while(i<=mid)
{
aptr[k++]=bptr[i++];
}
}//function
The statement i<= mid && j<=hi is never true when your program executes, hence, the while loop that depends on it is never entered and your code that actually swaps elements is never reached.
After the for loop that precedes it, i is equal to hi, which is always greater than mid. I am guessing you mean to reset i to be equal to low before you enter that while loop.
Here's a suggestion for how to start: put printf() calls into your mergesort() and merge() functions that display the parameters at the start and return of each function call. That might help you figure out what's going on. Asking other people to debug your algorithm isn't going to to help you learn how to program.
As a sundry point I'd like to mention that you've fallen victim to error of possible integer overflow:
mid=(low+hi)/2;
If low and/or hi are big enough, low + hi will overflow, giving you the wrong value for mid. Instead you should do this:
mid = low + (hi - low) / 2;

Resources